所以我有两个表,一个有几个外键,都指向另一个表。
示例:
TableA
Id | FirstId | SecondId | ThirdId
1 | 10 | 11 | 12
2 | 13 | 14 | 15
和
TableB
Id | Value
10 | 'Cat'
11 | 'Dog'
12 | 'Rabbit'
13 | 'Bird'
14 | 'Hamster'
15 | null
现在我构建了一个查询,例如:
var entity = context.TableA
.Include(a => a.First)
.Include(a => a.Second)
.Include(a => a.Third)
.SingleOrDefault(a => a.Id == 1)
现在,根据我构建查询的方式,我可以大致得到两个结果中的一个。如果我使用上面的示例,我将返回一个实体,但SecondId可能是11并且设置了所有正确的属性,但FirstId和ThirdId可能具有值15并且所有属性都将为null( Id是随机但一致的,并且对于所有查询始终相同,直到我重建数据库)。现在,如果我将SingleOrDefault(...)替换为:
.With(a => a.Id == 1).SingleOrDefault()
我将分别返回一个实体,其FirstId,SecondId和ThirdId分别为10,11,12(正确),但只有a.Second会设置任何属性。 a.First.Value和a.Third.Value都将为null。此外,它始终是正确的SecondId,从不是第一或第三。
所以我的问题是,EntityFramework不支持单个表与另一个表有多个关系的想法,还是我缺少某些东西,或者?
我已经尝试检查LINQ生成的查询但是当我对数据库运行它时,我得到了所有正确的值。我尝试改变构建LINQ查询的方式,并且在使用.Include(...)和.Load()之间进行了交换。当我使用.Load()时,不正确的Ids(在我的第一个例子中为15)实际上会在每次调用.SaveChanges()时传播回数据库,即使我什么都没做但是:
using(MyDatabase context = new MyDatabase())
{
context.TableB.Load();
context.SaveChanges();
}
我使用的是EntityFramework 6和一个SqlCE 4.0数据库。
TableA&的课程表B(注意这些是从edmx模型自动生成的):
public partial class TableA
{
public int Id { get; set; }
private int FirstId { get; set; }
private int SecondId { get; set; }
private int ThirdId { get; set; }
public virtual TableB First { get; private set; }
public virtual TableB Second { get; private set; }
public virtual TableB Third { get; private set; }
}
public partial class TableB
{
public int Id { get; set; }
public string Value { get; set; }
}
我现在也尝试将提供程序从System.Data.SqlServerCe.4.0切换到System.Data.SqlClient(并将数据库移动到SQLExpress实例),我得到了相同的结果。
答案 0 :(得分:0)
我认为生成的类有一点bug。您可以尝试更改下面的TableA,然后再试一次吗?
public class TableA
{
public int Id { get; set; }
[ForeignKey("First")]
private int? FirstId { get; set; }
[ForeignKey("Second")]
private int? SecondId { get; set; }
[ForeignKey("Third")]
private int? ThirdId { get; set; }
public virtual TableB First { get; private set; }
public virtual TableB Second { get; private set; }
public virtual TableB Third { get; private set; }
}
答案 1 :(得分:0)
所以我觉得自己像个白痴,但实际上我发现了这个问题。在我开始升级以使用EntityFramwork之前还有另一个部分类:
public partial class TableA
{
public static readonly TableB DefaultTableBValue = new TableB(null);
public TableA()
{
this.First = TableA.DefaultTableBValue;
this.Second = TableA.DefaultTableBValue;
this.Third = TableA.DefaultTableBValue;
}
}
public partial class TableB
{
public TableB(string value)
{
this.Value = value;
}
}
这显然会混淆EntityFramework的对象映射器,当它实例化一个新对象时(在从数据库返回之前),它会看到First,Second和Third值发生变化,并尝试将它们提交回数据库或它不会复制'默认值',只是按原样返回对象。一旦我删除了这个不需要的部分课程,一切都完美无瑕。
长话短说,小心创建默认构造函数并修改任何数据库属性。 EntityFramework在检测到构造函数中的值更改时似乎不知道该怎么做。