我已经为每个客户建立了一个系统,它有一个核心解决方案和一个自定义解决方案。Core有自己的dbcontext,每个海关对于特定于客户端的表都有自己的dbcontext。自定义解决方案引用核心解决方案dll。自定义dll正在由插件体系结构中的Core解决方案动态加载。由于Core和Custom有自己的dbcontext,所以每个dbcontext都有自己的迁移文件。
除了一件事外,我不能做一个连接核心表和自定义表的linq查询。(例:在一个查询中将ProjectCustom与Project连接起来)。我知道错误:
The specified LINQ expression contains references to queries that are associated with different contexts.因此,为了允许来自Core和Custom的查询连接表,我正在考虑走另一条路线,其中Core定义一个基本抽象DbContext,而Custom则从这个dbcontext继承并添加它的自定义表。所以我在运行时只有一个dbcontext。
现在,对于我的问题,是否可以在Core中使用迁移文件,以及在自定义中定义另一组迁移文件?
我已经制定了一个工作解决方案,在自定义解决方案中维护所有迁移。但是,我不喜欢这样一个事实:如果我进行了影响核心表的手动迁移,我必须手动地将它传播到所有自定义解决方案。
我希望将影响核心表的迁移保留到核心解决方案中,并为海关提供另一组迁移。它们都应用于相同的dbcontext,最终实现驻留在自定义解决方案中。
这有可能吗?有任何方法来配置迁移文件的某种提供程序吗?因此,我可以首先应用在Core解决方案中定义的迁移,然后使用相同的dbcontext从自定义中应用迁移。
发布于 2017-04-18 22:26:12
让我们首先为上下文的配置创建一个接口
public interface IDbContextRegistry
{
void Configure(DbModelBuilder builder);
}在我的例子中,实现存在于每个单独的上下文中,但是在diff类中实现这一点将是很好的。
public class ContextA : DbContext, IDbContextRegistry
{
static ContextA()
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<ContextA, ConfigurationA>());
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
Configure(modelBuilder);
}
public void Configure(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<ModelA>();
}
}
internal sealed class ConfigurationA : DbMigrationsConfiguration<ContextA>
{
public ConfigurationA()
{
AutomaticMigrationsEnabled = false;
}
protected override void Seed(ContextA context)
{
}
}
public class ModelA
{
public int Id { get; set; }
public string Name { get; set; }
}和
public class ContextB : DbContext, IDbContextRegistry
{
static ContextB()
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<ContextB, ConfigurationB>());
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
Configure(modelBuilder);
}
public void Configure(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<ModelB>();
}
}
internal sealed class ConfigurationB : DbMigrationsConfiguration<ContextB>
{
public ConfigurationB()
{
AutomaticMigrationsEnabled = false;
}
protected override void Seed(ContextB context)
{
}
}
public class ModelB
{
public int Id { get; set; }
public DateTimeOffset Date { get; set; }
}稍后在您的主要应用程序创建一个上下文,将注册所有的个人类型。
public class ContextJoin : DbContext
{
private readonly List<IDbContextRegistry> _registry = new List<IDbContextRegistry>();
// Constructor to allow automatic DI injection for most modern containers
public ContextJoin(IEnumerable<IDbContextRegistry> registry)
{
_registry.AddRange(registry);
}
public ContextJoin(params IDbContextRegistry[] registry) : this(_registry.AsEnumerable())
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
foreach (var entry in _registry)
{
entry.Configure(modelBuilder);
}
}
}瞧,每个实体都生活在ContextJoin中,随时准备使用。示例:
class Program
{
static void Main(string[] args)
{
ContextA ctxA = new ContextA();
ctxA.Set<ModelA>().Add(new ModelA());
ctxA.SaveChanges();
ContextB ctxB = new ContextB();
ctxB.Set<ModelB>().Add(new ModelB());
ctxB.SaveChanges();
ContextJoin ctxJoin = new ContextJoin(ctxA, ctxB);
ctxJoin.Set<ModelB>().Add(new ModelB());
ctxJoin.Set<ModelA>().Add(new ModelA());
ctxJoin.SaveChanges();
var crossQuery = ctxJoin.Set<ModelA>().Join(
ctxJoin.Set<ModelB>(), t => t.Id, t => t.Id, (a, b) => new
{
a.Name,
b.Date
}).ToList();
crossQuery.ForEach(t => Console.WriteLine($"Name: {t.Name}, Date: {t.Date}"));
}
}希望能帮上忙!
https://stackoverflow.com/questions/43396067
复制相似问题