关于实体框架:EF5使用DBSet.Find()进行代码优先的TPH映射错误

EF5 Code first TPH Mapping error using DBSet.Find()

在首先使用Entity Framework 5代码并按表分层结构时。
这与存储库和工作单元结合在一起(尝试了几种实现方式)。
我遇到以下错误:

(34,10) : error 3032: Problem in mapping fragments starting at lines 19, 34:EntityTypes T, T are being mapped to the same rows in table T. Mapping conditions can be used to distinguish the rows that these types are mapped to.

我已使用以下指南解决了此问题:
实体框架4.3-TPH映射和迁移错误

当使用所有记录的常规查找时,此方法有效,然后没有错误。

使用DBSet<T>.Find(id)时,收到上述错误消息。

使用DBSet<T>.Where(t => t.id == id)时一切正常。

请问有人有解决此问题的方法吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
public class TDataContext : DbContext
{
    // Models
    public abstract class BaseTrackable
    {
        public DateTime DateModified { get; set; }
    }

    public abstract class ParentClass : BaseTrackable
    {
        public int ParentId { get; set; }
        public string ParentString { get; set; }
    }

    public class Foo : ParentClass
    {
        public string FooString { get; set; }
    }

    public class Bar : ParentClass
    {
        public string BarString { get; set; }
    }

    // Configuration
    public class ParentConfiguration : EntityTypeConfiguration<ParentClass>
    {
        public ParentConfiguration()
        {
            ToTable("Parent");
        }
    }

    public class FooConfiguration : EntityTypeConfiguration<Foo>
    {
        public FooConfiguration()
        {
            Map(m => m.Requires("FooIndicator").HasValue(true));
        }
    }

    public class BarConfiguration : EntityTypeConfiguration<Bar>
    {
        public BarConfiguration()
        {
            Map(m => m.Requires("BarIndicator").HasValue(true));
        }
    }

    public DbSet<ParentClass> Parent { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations
            .Add(new ParentConfiguration())
            .Add(new FooConfiguration())
            .Add(new BarConfiguration());
    }

}

public class Controller
{
    TDataContext _context = new TDataContext();

    // Repository function
    public T GetById< T >(object id) where T : class
    {
        var dbset = _context.Set< T >();
        return dbset.Find(id);
    }

    public IQueryable<TDataContext.Foo> GetFiltered(Expression<Func<TDataContext.Foo, bool>> filter)
    {
        var dbset = _context.Set<TDataContext.Foo>();
        return dbset.Where(filter);
    }

    // Final call
    // Which fails..
    public TDataContext.Foo Get(int id)
    {
        return this.GetById<TDataContext.Foo>(id);
    }

    // This works...
    public TDataContext.Foo GetWhere(int id)
    {
        return this.GetFiltered(f => f.ParentId == id).FirstOrDefault();
    }
}


会不会更好

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class FooConfiguration : EntityTypeConfiguration<Foo>
{
    public FooConfiguration()
    {
        Map(m => m.Requires("Type").HasValue("Foo"));
    }
}

public class BarConfiguration : EntityTypeConfiguration<Bar>
{
    public BarConfiguration()
    {
        Map(m => m.Requires("Type").HasValue("Bar");
    }
}

通过这种方式,FooConfiguration不需要了解任何有关BarConfiguration的知识,反之亦然。从EF 4.3迁移到5.0时遇到了这个问题,我认为发生了变化的是在EF 5.0中区分数据库列不可为空。我认为它们不可为空更有意义,并且一般而言,对每个派生类型只使用一个discrimanotor列,而不是对每个类型使用一个列(如EF 4.3中那样)会更好。

-斯坦


找到了可以部分解决我的问题的东西...

在表中添加另一个指标时,没有更多错误,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class FooConfiguration : EntityTypeConfiguration<Foo>
    {
        public FooConfiguration()
        {
            Map(m => {
                m.Requires("FooIndicator").HasValue(true);
                m.Requires("BarIndicator").HasValue<short>(1);
            });
        }
    }

    public class BarConfiguration : EntityTypeConfiguration<Bar>
    {
        public BarConfiguration()
        {
            Map(m => {
                m.Requires("BarIndicator").HasValue(true);
                m.Requires("FooIndicator").HasValue<short>(0);
            });
        }
    }