And*_*tos 17 entity-framework fluent-interface mef entity-framework-4
背景:
我们有一个包含许多模块的项目.我们将EntityFramework 4.2与FluentAPI(CodeFirst)一起使用.
有一个名为Diverto.ORM.EntityFramework.SQLServer的中心项目,它包含使用FluentAPI构建上下文的部分类(并且它引用了解决方案中的所有其他项目).
最近我们收到了客户要求实施许多其他功能的请求,该解决方案还需要其他几个项目.其中一些项目将来自另一个系统(人力资源),一些将被创建.现有解决方案的核心是财务系统.
我们希望使用MEF"动态"启用和禁用这些新项目(以及GUI,业务逻辑和所有项目).它们将作为插件进行交互,应用程序的主菜单也将使用MEF进行填充.
但是,由于它们必须共享的数据,我们并不真正了解如何启用/禁用这些模块/项目(新模块/项目).
考虑一下:
- 使用DbSet <ClassA>和DbSet <ClassB>的DivertoContext(主上下文).
- 使用DbSet <ClassC>的PluginContext(来自插件).
现在,考虑到在GUI内部,我必须能够访问ClassA,ClassB和ClassC中的数据(如果插件存在的话).
找到解决方案 见下文
我注意到有人在检查这个并将其标记为最喜欢或最喜欢的.请记住,这个答案可以追溯到2012年,EntityFramework 自那以后发生了很大的变化.
另外,拜托,请,请记住,每个项目都有自己的需求.那时候,我需要这个功能.您的项目可能根本不需要这个,或者只是其中的一部分!
最后,只是为了确保一切都被掩盖,是的,可以使用EF 6.1和EF迁移来实现这一点,也可以使用其他ORM和迁移框架.
您可能需要一些其他接口,作为迁移加载的接口,并正确处理特定的插件迁移(不要将其与其他插件混合使用,因此请尝试为每个插件实现某种独特的令牌).
And*_*tos 28
好吧,我会试着在这里解释,因为我在其他地方找不到.对于必须创建将接收多个插件的单个基础软件且这些插件必须与单个数据库中的现有数据交互的人来说,这很有趣.
首先,我将使用CodeFirst API和所有的Entity Framework.因此,如果您要进行此操作,我建议您从MSDN和MSDN的Code First Fluent API中读取EntityTypeConfiguration.
现在,让我们解释一些事情:
解决方案: MEFTest
项目:
在Base.ORM项目中,根据您的需要使用方法创建Generic Repository接口,但不输入接口.它将类似于:
public interface IRepository
{
bool Add<T>(T item);
}
Run Code Online (Sandbox Code Playgroud)
从现在开始,我将其称为IRepository以保持简单.
我将考虑一种名为Add(T item)的方法用于样本编码.
在Base.ORM.EntityFramework.SQLServer内部创建一个继承自DbContext并实现IRepository的BaseContext类.它应该如下所示:
public class BaseContext : IRepository
{
public bool Add<T>(T item)
{
try { Set<T>().Add(item); return true; }
catch { return false; }
}
}
Run Code Online (Sandbox Code Playgroud)
您可以在此处添加自定义IDatabaseInitializer基本实现以进行数据库版本控制.我已经用SQL文件winthin标准文件夹完成了它,但这是旧的编码,因为EF现在支持迁移.
如果您仍然需要手动处理,请记住将数据库设置为单用户模式BEFORE并在之后恢复为多用户模式.记住:尝试...捕捉......最终会在这里帮助,因为你可以在最终内部恢复到多用户,所以即使在出错时也不会留下任何问题.
在SampleApplication项目中,添加:
ClassA(int Id,string Name)和ClassB(int Id,DateTime TestDate).
在SampleApplication.ORM.EntityFramework.SQLServer中创建标准上下文.
我将在这里使用三个非常有趣的名称:ClassA,ClassB和ClassC.
ClassA和ClassB都是从这个项目引用的,它将是这样的:
public class Context : BaseContext
{
public DbSet<ClassA> ClassA { get; set; }
public DbSet<ClassB> ClassB { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
/* I'll talk about this later. Just override the OnModelCreating and leave it */
base.OnModelCreating(modelBuilder);
}
}
Run Code Online (Sandbox Code Playgroud)
现在有趣的部分:该插件将有这样的方法:
public void Setup(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<ClassC>().ToTable("ClassC");
modelBuilder.Entity<ClassC>().HasKey(_classC => _classC.Id);
modelBuilder.Entity<ClassC>().Property(_classC => _classC.Date2).HasColumnType("datetime2").HasPrecision(7);
}
Run Code Online (Sandbox Code Playgroud)
当然,ClassC在插件项目中.您没有从主项目中引用它.
您必须使用MEF以及接口找到此方法(安装程序).我只是展示WHERE放置它以及如何使它工作=)
回到Context类,OnModelCreating方法将如下所示:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<ClassA>().ToTable("ClassA");
modelBuilder.Entity<ClassA>().HasKey(_classA => _classA.Id);
modelBuilder.Entity<ClassB>().ToTable("ClassB");
modelBuilder.Entity<ClassB>().HasKey(_classB => _classB.Id);
modelBuilder.Entity<ClassB>().Property(_classB => _classB.TestDate).HasColumnType("datetime2").HasPrecision(7);
/* Use MEF to load all plugins. I'll use the mock interface IPlugin */
foreach (IPlugin plugin in MefLoadedPlugins)
plugin.Setup(modelBuilder);
}
Run Code Online (Sandbox Code Playgroud)
在您的APP中,您将只有一个上下文.此上下文继承自实现IRepository的BaseContext.考虑到这一点,您需要编写GUI和业务层代码以使用IRepository(来自Base.ORM)和特定类(在特定于业务的dll中).
好吧,它在这里工作.
我想我已经在这里展示了所有相关部分.
当然,类中有更多的代码,但事实并非如此.我试图只显示你真正需要创建/实现它来完成它.
感谢来自SO和MSDN的人们,我已经找到了很多评论和其他帖子.
感谢Caio Garcia(BR)帮助我提供了有关其他基于插件的系统的一些说明.
以下是一些示例代码:
public class ClassA
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ClassB
{
public int Id { get; set; }
public string OtherName { get; set; }
}
public interface IRepository
{
bool Add<T>(T item);
bool Save();
}
public class BaseContext : DbContext, IRepository
{
public bool Add<T>(T item)
{
try { Set<T>().Add(item); return true; } catch { return false; }
}
public bool Save()
{
try { SaveChanges(); return true; } catch { return false; }
}
}
public class Context : BaseContext
{
// Fill this list using MEF - check for the IPluginContext interface on assemblies
public List<IPluginContext> MefLoadedPlugins;
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<ClassA>().ToTable("TableB", "Schema_1");
modelBuilder.Entity<ClassA>().HasKey(_a => _a.Id);
modelBuilder.Entity<ClassB>().ToTable("TableB", "Schema_1");
modelBuilder.Entity<ClassB>().HasKey(_b => _b.Id);
if (MefLoadedPlugins != null)
foreach (var pluginContext in MefLoadedPlugins)
pluginContext.Setup(modelBuilder);
}
}
Run Code Online (Sandbox Code Playgroud)
public class ClassC
{
public int Id { get; set; }
public string Description { get; set; }
}
public interface IPluginContext
{
void Setup(DbModelBuilder modelBuilder);
}
public class Just_A_Sample_Plugin_Context : IPluginContext
{
public void Setup(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<ClassC>().ToTable("TableC", "Schema_2");
modelBuilder.Entity<ClassC>().HasKey(_c => _c.Id);
}
}
Run Code Online (Sandbox Code Playgroud)
public void DoSomething(IRepository repo)
{
var classA = new ClassA() { Name = "First Name" };
repo.Add(classA);
repo.Save();
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6232 次 |
| 最近记录: |