我正在尝试使用我正在处理的项目实现一些图层分离。我的想法是,我可以利用网站的任何功能并对其进行模块化。例如,如果您使用新闻等内容并希望将该功能添加到网站,那么在代码中您只需要导入新闻服务以及模型,数据层等。所有内容都随之导入。
请注意,我使用Ninject作为项目的一部分来注入依赖项,这样我就不需要引用具体的类,我只引用契约。
我有我的主项目和数据层这样:
public class MainDbContext : CustomIdentityDbContext, IMainDbContext
{
}
正如您所看到的,它扩展了CustomIdentityDbContext,如下所示:
public class CustomIdentityDbContext : IdentityDbContext<CustomUser>, ICustomIdentityDbContext
{
public CustomIdentityDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<IdentityUserClaim>().ToTable("UserClaim");
modelBuilder.Entity<IdentityUserRole>().ToTable("UserRole");
modelBuilder.Entity<IdentityUserLogin>().ToTable("UserLogin");
modelBuilder.Entity<IdentityRole>().ToTable("Role");
modelBuilder.Entity<AzularisUser>().ToTable("User");
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
}
public static DbContext Create()
{
return new CustomIdentityDbContext();
}
}
我的问题是我需要一个新闻表,然后我需要EF6映射该表,就像它对身份一样。我无法弄清楚如何建立这种关系。如何将DbSet<News> News { get; set; }
添加到我的MainDbContext中,而无需在那里写入该行并引用新闻对象。所以当我引用我的服务时,我正试图动态地将它添加到我的MainDbContext类中,因为该服务将触发所有其他类通过ninject和binding创建自己。
换句话说,新闻数据层需要将自己注入到MainDbContext中,而不需要MainDbContext在其引用中知道它。这样的事情可能吗?如果是这样,我将如何实现它?
以下是我的尝试:
public class NewsDbContext : DbContext, INewsDbContext
{
public DbSet<News> News { get; set; }
public NewsDbContext() : base("DefaultConnection") { }
public IEnumerable<INews> QueryNews()
{
return News;
}
}
上面的代码编译并运行,但是,它没有创建表,当我尝试查询或插入记录时,它会因表格不存在而中断。我不太确定如何实现这一目标,而且我非常想法。这样的事情可能吗?
编辑:
我意识到我可能没有正确解释自己。让我再尝试一次。我有一个多层结构。我有服务,数据,域和DTO图层。这4个层组成了一个插件。在这4层之上,我还有4层是这些层的接口,换句话说就是契约。我使用Ninject将我的契约绑定到实现层,这样主项目就不会实际引用项目中的实现层。出于这个原因,我试图将数据层插入到主项目的数据层中,而主项目数据层实际上并没有引用插件的数据层。问题是该插件将拥有自己需要的表。我希望在第一次运行项目时使用EF6自动创建这些表。
我的主要项目也以与插件相同的方式拆分,它有4层,还有一个Manager层。经理是服务的集合,没有任何其他目的,它只是在Ninject的帮助下基于合同实例化它们。项目的核心包含所有视图,脚本和css文件,但它引用了管理器的界面。使用ninject,我创建了一个管理器实例。经理再次拥有对合同的所有引用,并且与ninject一起创建了这些合同的实例。服务引用数据层的合同,数据层将查询信息并将结果带回服务,该服务将被传递回控制器。我希望这能更好地解释我的结构。通过这种方法,我试图创建一个trully模块化项目,您可以交换dll的实现并让项目继续工作,无需重新编译整个darn事物。我可以在2个dll上有两个完全相同的功能,但只要他们实现相同的合同,网站应该工作,无论它在其文件夹中有哪个dll。
我刚刚描述的所有内容都适用于使其适用于EF6的例外。我有一个与DAPPER非常相似的结构,当你编写自己的查询时,它们都很漂亮和花花公子,所以我没有遇到任何问题。我试图用EF6复制这个。所以再一次,我的问题是,如何让EF6创建表,当引用的唯一东西是服务接口时,如何动态添加它们。也许界面可以有MapTables功能,但我不知道如何完成动态添加到EF6。
我有一个想法,我不确定这是否可行,也不知道我会怎么做,但如果我将DB上下文作为一种类型而不是扩展它呢?
答案 0 :(得分:1)
我已经部分解决了我的问题。一旦我有完整的解决方案,我会将此作为答案发布并更新。到目前为止,我已经学会了如何生成表格。在主项目的DB Context中使用以下代码:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
var entityMethod = typeof(DbModelBuilder).GetMethod("Entity");
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
var entityTypes = assembly
.GetTypes()
.Where(t =>
t.GetCustomAttributes(typeof(PersistentAttribute), inherit: true)
.Any());
foreach (var type in entityTypes)
{
entityMethod.MakeGenericMethod(type)
.Invoke(modelBuilder, new object[] { });
}
}
base.OnModelCreating(modelBuilder);
}
上面的代码将确保为添加了“PersistentAttribute”的任何类创建表。我的下一个问题是尝试从外部DLL查询。因此,新闻项目的数据层需要能够通过以某种方式传递在主项目中创建的上下文来查询自身。由于ninject,我对此几乎没有什么想法,一旦我弄明白,我会发布更多。