如果一个实体有多个关系,并且我尝试同时插入数据,则EF会抛出InvalidCastException.
举个例子,想象一下这些域类:
public class Person : Entity<Guid>
{
public string Name { get; set; }
public ICollection<Watch> Watches { get; set; }
public ICollection<Shoe> Shoes { get; set; }
}
public class Shoe : Entity<Guid>
{
public string Brand { get; set; }
}
public class Watch : Entity<Guid>
{
public string Brand { get; set; }
}
用例#1(完美工作):
using (var context = new MultipleRelationshipsContext())
{
var watches =
new List<Watch>() {
new Watch { Brand = "Rolex" }
};
context.Set<Person>().Add(
new Person
{
Name = "Warren Buffett",
Watches = watches
}
);
}
用例#2(也完美地工作):
using (var context = new MultipleRelationshipsContext())
{
var shoes =
new List<Shoe>() {
new Shoe { Brand = "Cole Haan" }
};
context.Set<Person>().Add(
new Person
{
Name = "Barack Obama",
Shoes = shoes
}
);
}
用例#3(InvalidCastException):
using (var context = new MultipleRelationshipsContext())
{
var watches =
new List<Watch>() {
new Watch { Brand = "Casio" }
};
var shoes =
new List<Shoe>() {
new Shoe { Brand = "New Balance" }
};
context.Set<Person>().Add(
new Person
{
Name = "Steve Jobs",
Watches = watches,
Shoes = shoes
}
);
}
在第三种情况下,抛出InvalidCastException,表示EF无法从’EntityFrameworkMultipleRelationships.Entities.Watch转换为’EntityFrameworkMultipleRelationships.Entities.Shoe’.
我是一名EF新手,但我觉得这里出了点问题.
我要感谢任何暗示可能的解决方案!
PD.:为了尽可能快地测试自己,请下载此VS2012解决方案:https://dl.dropboxusercontent.com/u/22887057/EntityFrameworkMultipleRelationships.zip.按照README.txt按照代码优先模式创建数据库.
UPDATE
正如@Chris指出的那样,问题在于EF认为Shoe和Watch实体是相同的.这是由于实施的覆盖等于错误造成的.这实际上是问题的根源:
public abstract class Entity<T>
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Column("Id")]
public T Id { get; set; }
public override bool Equals(object obj)
{
Entity<T> entityOfT = obj as Entity<T>;
if (entityOfT == null)
return false;
return object.Equals(this.Id, entityOfT.Id);
}
public override int GetHashCode()
{
return this.Id.GetHashCode();
}
}
如果两个不同的实体类型(如Watch和Shoe)具有相同的Id,则EF正在考虑它们等于.
添加运行时类型检查以覆盖Equals会考虑实体类型,因此可以解决此问题.
...
return this.GetType() == entityOfT.GetType() && object.Equals(this.Id, entityOfT.Id);
...
最佳答案 我不确定实体框架的内部结构(虽然我可能会尝试看一看),但我认为你的问题可能是两件事的组合:
1)实体框架自动生成存储实体的集合的方式.
2)你有两个具有相同Guid的子对象,它们将返回Equals(..)true,即使它们的类型不同.
如果您要么:
定义Shoe / Watch(或两者),并将它/它们添加到相应的集合中:
context.Set<Shoe>().Add(aShoe);
或者为手表或鞋子的Guid定义不同的值
Watch tWatch = new Watch { Brand = "Casio", Id = new System.Guid("00000000-0000-0000-0000-000000000001") };
如果你不做其中任何一个,并按照你的第三个例子,你可以通过调试器,发现你将达到一个用Watch and Shoe调用Equals的点,结果是真的 – 我假设这就是Entity Framework抛出异常的重点.
希望能够了解更多关于EF内部结构的人能够指出为什么会这样.