Skip to content

Instantly share code, notes, and snippets.

@hikalkan
Last active June 11, 2016 20:48
Show Gist options
  • Save hikalkan/e035271493fa9fbd7fa026d44c690aa9 to your computer and use it in GitHub Desktop.
Save hikalkan/e035271493fa9fbd7fa026d44c690aa9 to your computer and use it in GitHub Desktop.
DbContextTypeMatcher test
using System;
using System.Collections.Generic;
using System.Linq;
using Abp.Collections.Extensions;
using Abp.Dependency;
using Abp.Domain.Uow;
using Abp.EntityFramework.Repositories;
using Abp.MultiTenancy;
namespace Abp.EntityFramework
{
public class MyDbContextTypeMatcher : IDbContextTypeMatcher
{
private readonly ICurrentUnitOfWorkProvider _currentUnitOfWorkProvider;
private readonly Dictionary<Type, List<Type>> _dbContextTypes;
public MyDbContextTypeMatcher(ICurrentUnitOfWorkProvider currentUnitOfWorkProvider)
{
_currentUnitOfWorkProvider = currentUnitOfWorkProvider;
_dbContextTypes = new Dictionary<Type, List<Type>>();
}
public virtual void Add(Type sourceDbContextType, Type targetDbContextType)
{
if (!_dbContextTypes.ContainsKey(sourceDbContextType))
{
_dbContextTypes[sourceDbContextType] = new List<Type>();
}
_dbContextTypes[sourceDbContextType].Add(targetDbContextType);
}
public virtual Type GetConcreteType(Type sourceDbContextType)
{
//TODO: This can also get MultiTenancySide to filter dbcontexes
//TODO: Can be optimized by extracting/caching MultiTenancySideAttribute attributes for DbContexes.
//Get possible concrete types for given DbContext type
var allTargetTypes = _dbContextTypes.GetOrDefault(sourceDbContextType);
if (allTargetTypes.IsNullOrEmpty())
{
//Not found any target type, return the given type if it's not abstract
if (sourceDbContextType.IsAbstract)
{
throw new AbpException("Could not find a concrete implementation of given DbContext type: " + sourceDbContextType.AssemblyQualifiedName);
}
return sourceDbContextType;
}
if (allTargetTypes.Count == 1)
{
//Only one type does exists, return it
return allTargetTypes[0];
}
//Will decide the target type with current UOW, so it should be in a UOW.
if (_currentUnitOfWorkProvider.Current == null)
{
throw new AbpException("GetConcreteType method should be called in a UOW.");
}
var currentTenancySide = _currentUnitOfWorkProvider.Current.GetTenantId() == null
? MultiTenancySides.Host
: MultiTenancySides.Tenant;
var multiTenancySideContexes = allTargetTypes.Where(type =>
{
var attrs = type.GetCustomAttributes(typeof(MultiTenancySideAttribute), true);
if (attrs.IsNullOrEmpty())
{
return false;
}
return ((MultiTenancySideAttribute)attrs[0]).Side.HasFlag(currentTenancySide);
}).ToList();
//Try to get the DbContext which is for current multitenancy side.
if (multiTenancySideContexes.Count == 1)
{
return multiTenancySideContexes[0];
}
//Try to get the DbContext which not defined AutoRepositoryTypesAttribute
var defaultRepositoryContexes = allTargetTypes.Where(type => !type.IsDefined(typeof(AutoRepositoryTypesAttribute), true)).ToList();
if (defaultRepositoryContexes.Count == 1)
{
return defaultRepositoryContexes[0];
}
//Generating exception
if (multiTenancySideContexes.Count > 1)
{
throw new AbpException(string.Format(
"Found more than one concrete type for given DbContext Type ({0}) define MultiTenancySideAttribute with {1}. Found types: {2}.",
sourceDbContextType,
currentTenancySide,
multiTenancySideContexes.JoinAsString(", ")
));
}
throw new AbpException(string.Format(
"Found more than one concrete type for given DbContext Type ({0}) but none of them defines MultiTenancySideAttribute with {1}. Found types: {2}.",
sourceDbContextType,
currentTenancySide,
multiTenancySideContexes.JoinAsString(", ")
));
}
}
}
@Sampath-Lokuge
Copy link

More info about the issue.Please see that.

Alt Text

@Sampath-Lokuge
Copy link

Hi,
Shall I put this issue on the Main repo or is this place enough ?

@hikalkan
Copy link
Author

@mengvisal
Copy link

Hi! I also have the problem of "Found more than one concrete type for given dbcontext type" after I upgrade from 0.8.2.0 to 0.9.3.0. Actually, I use DD design and i have many bounded contexts based on modules i have. Those bounded contexts uses only one single database or one connection string. For 0.8.2.0 version, I can do it without any problems and no need to define a custom repository since different bounded contexts contain different entities mapping and ASP.NET Zero design is smart enough to use the right bounded context. Here, i would like to confirm, for version 0.9.3.0, do i need to define each custom repository for each bounded context i have or is there anyway I can still enjoy using one repository for all bounded contexts?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment