C# 实体框架中的泛型

C# 实体框架中的泛型,c#,entity-framework,linq-to-entities,C#,Entity Framework,Linq To Entities,我面临一个关于实体框架的难题。使用mvc 4和entity framework 5.0,我正在开发一个现有应用程序的附加组件,该应用程序具有以下表名: dbo.company1_contact dbo.company1_product dbo.company2_contact dbo.company2_product 用户通常只能访问公司1或公司2,我希望支持所有公司的用户。这需要一种通用的方法 因此,我创建了两个edmx文件,一个用于公司1,一个用于公司2,使用相同的实体和上下文名称。导致

我面临一个关于实体框架的难题。使用mvc 4和entity framework 5.0,我正在开发一个现有应用程序的附加组件,该应用程序具有以下表名:

dbo.company1_contact
dbo.company1_product
dbo.company2_contact
dbo.company2_product

用户通常只能访问公司1或公司2,我希望支持所有公司的用户。这需要一种通用的方法

因此,我创建了两个edmx文件,一个用于公司1,一个用于公司2,使用相同的实体和上下文名称。导致出现诸如

Entities.Company1.Contact
Entities.Company1.Product
Entities.Company2.Contact
Entities.Company2.Product
和两个上下文类:

Entities.Company1.Company1Entities
Entities.Company2.Company2Entities
public class Company1Entities : DbContext, IRepository 
{
    ...

    public DbSet<IProduct> Products { get; set; }
    public DbSet<IContact> Contacts { get; set; }
}
这还不足以以通用方式使用它,因为例如,控制器需要一个存储库变量,例如:

private Company1Entities db = new Company1Entities()
对于第二公司来说,这将是

private Company2Entities db = new Company2Entities()
通用方法是使用接口ICompanyEntities和工厂来获得正确的存储库。但是-上下文类中包含的DbSet属性可能具有相同的名称,但它们的类型不同。具体来说,例如,上下文类中的产品集现在定义为

DbSet<Entities.Company1.Product> Products  {}
对于每家公司:

public class Product : IProduct {} 
在上下文类中:

Entities.Company1.Company1Entities
Entities.Company2.Company2Entities
public class Company1Entities : DbContext, IRepository 
{
    ...

    public DbSet<IProduct> Products { get; set; }
    public DbSet<IContact> Contacts { get; set; }
}
公共类公司1实体:DbContext,IRepository
{
...
公共数据库集产品{get;set;}
公共数据库集联系人{get;set;}
}
这很好,我希望问题得到解决。但是实体框架在很大程度上被阻塞了,所以我不得不完全回滚

然后我尝试对db变量使用dynamic关键字,但linq不接受。
有人能给我解释一下如何解决这个问题吗?我开始觉得这在实体框架中是不可能的,除非我将我的控制器编写为partials,并为每个公司实现一个控制器,只包含声明db变量的行。这是我真的不想做的事情,我宁愿完全复制controller类。是否有一种解决方案,一种通用的方法?我是不是遗漏了什么?非常感谢您的帮助。

因为它们都是相同的精确模型,所以您可以使用相同的上下文。只需根据客户的不同加载数据即可。在构造函数中获取一个表示表前缀的值,然后重写
OnModelCreating
方法以在表映射上设置该前缀

public class GenericEntities : DbContext, IRepository 
{
    //...

    private string TablePrefix { get; set; }

    public GenericEntities(string tablePrefix)
    {
        this.TablePrefix = tablePrefix;
    }

    public DbSet<Product> Products { get; set; }
    public DbSet<Contact> Contacts { get; set; }

    public override OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Product>.ToTable(TablePrefix + "_product");
        modelBuilder.Entity<Customer>.ToTable(TablePrefix + "_customer");
    }
}

因为它们都是相同的精确模型,所以可以对它们使用相同的上下文。只需根据客户的不同加载数据即可。在构造函数中获取一个表示表前缀的值,然后重写
OnModelCreating
方法以在表映射上设置该前缀

public class GenericEntities : DbContext, IRepository 
{
    //...

    private string TablePrefix { get; set; }

    public GenericEntities(string tablePrefix)
    {
        this.TablePrefix = tablePrefix;
    }

    public DbSet<Product> Products { get; set; }
    public DbSet<Contact> Contacts { get; set; }

    public override OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Product>.ToTable(TablePrefix + "_product");
        modelBuilder.Entity<Customer>.ToTable(TablePrefix + "_customer");
    }
}

just.Other.programmer的回答是正确的,但不适用于我的情况,因为我首先使用的是数据库。相反,我现在使用T4生成通用实体, 我为每个实体和公司创建代码,如

IQueryable<GenericCustomer> Customers 
{
    get
    {
        return from c in db.Customers1
                select new GenericCustomer() 
                { Name = c.Name, ... }
    }
}
IQueryable客户
{
得到
{
在db.Customers1中从c返回
选择新的GenericCustomer()
{Name=c.Name,…}
}
}

这解决了我的大部分问题。

just.Other.programmer的回答是正确的,但不适用于我的情况,因为我首先使用数据库。相反,我现在使用T4生成通用实体, 我为每个实体和公司创建代码,如

IQueryable<GenericCustomer> Customers 
{
    get
    {
        return from c in db.Customers1
                select new GenericCustomer() 
                { Name = c.Name, ... }
    }
}
IQueryable客户
{
得到
{
在db.Customers1中从c返回
选择新的GenericCustomer()
{Name=c.Name,…}
}
}

这就解决了我的大部分问题。

这还不足以以通用方式使用它
-实际上,那些
xxxenties
类派生自
System.Data.Entities.ObjectContext
,因此您可以声明该类型的成员并引用它。是的,但这不能为我提供正确的DbSet属性。
这还不足以以通用方式使用它
-实际上,那些
xxxenties
类派生自
System.Data.Entities.ObjectContext
,因此您可以声明该类型的成员并引用它。是的,但这并不能为我提供正确的DbSet属性?每次实例化GenericeEntities时?或者只调用一次?@usr默认情况下,它在
GenericEntities
的第一次实例化时被调用,然后被缓存。您可以使用
modelBuilder.ModelCaching=false
禁用缓存,或者使用自定义缓存编写自定义模型生成器。我将更新答案以反映这一点。@gd73这是针对代码优先(即
DbContext
)奇怪的是,它似乎对某些实体有效,但对其他实体无效。正在调查..OnModelCreating何时运行?每次实例化GenericeEntities时?或者只调用一次?@usr默认情况下,它在
GenericEntities
的第一次实例化时被调用,然后被缓存。您可以使用
modelBuilder.ModelCaching=false
禁用缓存,或者使用自定义缓存编写自定义模型生成器。我将更新答案以反映这一点。@gd73这是针对代码优先(即
DbContext
)奇怪的是,它似乎对某些实体有效,但对其他实体无效。调查。。