实体框架6与POCO仅使用某些类

时间:2016-05-10 08:17:51

标签: c# entity-framework-6

我在另一个互连的VS项目中使用了多个类,例如:

namespace MyOtherProject
{
    public class A {
        public string Name {get;set;}
    }

    public class B {
        public int Value {get;set;}
        public A Child {get;set;}
    }
}

现在我想首先在EF中将这些类用作代码的POCO。但是我不需要数据库中的所有类,只需要其中的一些。所以我创建了一个上下文:

public class MyContext : DbContext
{
    public MyContext () : base("MyContext ")
    {
    }

    public DbSet<B> Bs { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    }
}

当我尝试运行项目时,我收到此错误:

  

System.Data.Entity.ModelConfiguration.ModelValidationException:一个或   在模型生成期间检测到更多验证错误:   MyProject.A:名称:架构中的每个类型名称必须是唯一的。类型   名称'A'已定义。

请注意,错误中的命名空间与A类的定义不同,因为我的A类是在另一个(共享)项目中定义的。相反,命名空间是上下文之一。

https://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/creating-an-entity-framework-data-model-for-an-asp-net-mvc-application上我读到了这个:

  

您可以省略DbSet和DbSet   声明,它将工作相同。实体框架会   隐式包含它们,因为Student实体引用了   注册实体和注册实体引用课程   实体。

我的假设(未确认)是EF看到B引用A但没有类型A的数据集,因此它在内部生成A类,然后突然发现有两个这样的类。

任何人都知道确切的问题是什么以及我可以做些什么来解决它?我有太多我不需要的课程,所以我不想为每个课程创建数据集。

1 个答案:

答案 0 :(得分:2)

首先,从Type1获取所有泛型类型参数(Type2DbSet<Type1> ...)。然后你应该检查每种类型的内部属性类型,即对其他类型的引用(作为直接链接或通过ICollection集), - 如果这个内部类型不存在于第一个 tablesTypes 我们会忽略它们。

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {         
        //other stuff.....

        Func<Type, bool> genericFilter = x => typeof(IEnumerable).IsAssignableFrom(x) && x.GenericTypeArguments.Length == 1;

        //All types of your context tables
        var tablesTypes = GetType().GetProperties()
            .Where(x => genericFilter(x.PropertyType))
            .Select(x => x.PropertyType.GenericTypeArguments.First());

        var namespaces2ignore = new List<string> { "Namespace2Ignore1", "Namespace2Ignore2" };
        var toIgnore = new List<Type>();
        foreach (var type in tablesTypes)
            //Ignore internal types, which not exist at tablesTypes
            toIgnore.AddRange(type.GetProperties()
                .Select(x => genericFilter(x.PropertyType) ? x.PropertyType.GenericTypeArguments.First() : x.PropertyType)
                .Where(x => !tablesTypes.Contains(x) && namespaces2ignore.Contains(x.Namespace)
                /*or as you suggested: && typeof(A).Assembly == x.Assembly*/
            ).ToList());            

        modelBuilder.Ignore(toIgnore);
    }

如果要在特定对类型属性上添加条件,可以执行以下操作:

    foreach (var type in tablesTypes)
        foreach(var prop in type.GetProperties()
            .Select(x => new { type = genericFilter(x.PropertyType) ? x.PropertyType.GenericTypeArguments.First() : x.PropertyType, prop = x })
            .Where(x => !tablesTypes.Contains(x.type) && namespaces2ignore.Contains(x.type.Namespace)                
        ).ToList())
            if(!(type == typeof(TestType) && prop.prop.Name == "Test"))
                toIgnore.Add(prop.type);

现在不会被排除在名称&#34;测试&#34;&#34;类型为TestType