在我的MVC4项目中,我试图通过使用EF5将我从excel工作表填充的一些数据插入数据库(使用12c ODAC的Oracle 10g DB)。
故事:
首先,我从excel读取数据,然后将它们转换为实体。但是,excel数据没有主键(ID)列(我没有控制超级EXCEL数据)。因此,对于excel中的每一行,我首先搜索DB以获得匹配。如果匹配,我将使用DbContext获取匹配的实体。在这种情况下,我的实例化类/实体已经填充了ID属性。
另一方面,如果DB中没有匹配,我将实例化一个没有ID信息的新类实体类型。如果实体存在于excel工作表的多行中,则我的最终List将具有同一实体的多个实例,每个实例具有ID = 0.
填充数据后,我将我的实体逐个添加到我的DbContext中,并调用上下文的SaveChanges()方法。然后,当我检查数据库时,我看到同一个类的不同实例获得不同的ID,但这不是我想要的。
我理解为什么会发生这种情况,因为如果没有设置PK,DbContext就无法关联类的不同实例。所有实体的EntityState都变为已添加:(
我的问题是:
“有没有办法告诉实体框架,如果”实体的所有属性彼此相等&&未设置PK / ID“在插入数据库时将这些实体视为相同的实体?”。
简化为:
在下面的代码中执行MyMethod()后,我只想在我的数据库表中创建一行数据:
// I implemented IEquatable to see if it works for EF (I heard it works in NHibernate) but unfortunately not working.
public class MyEntity(): IEquatable<MyEntity>
{
// This is an autoincrementing PK in DB
public int ID { get; set; }
public string Name { get; set; }
public bool Equals(MyEntity other)
{
if (other == null) return false;
if (ReferenceEquals(this, other)) return true;
return Equals(this.ID, other.ID) && Equals(this.Name, other.Name);
}
public override bool Equals(object obj)
{
return Equals(obj as MyEntity);
}
public override int GetHashCode()
{
unchecked
{
var result = this.ID.GetHashCode();
result = (result * 397) ^ (this.Name!= null ? this.Name.GetHashCode() : 0);
return result;
}
}
}
public void MyMethod()
{
DbContext db = new DbContext();
db.MyEntity.Add(new MyEntity { Name = "Foo" }) // ID=0 initially.
db.MyEntity.Add(new MyEntity { Name = "Foo" }) // ID=0 initially.
// When I check, the Entities in ChangeTracker are Equal!
// This is equal to 1.
int distinctNewEntryCount = db.ChangeTracker.Entries<MyEntity>().Select(e => e.Entity).Distinct().Count();
// This is equal to 2.
// But I want it to be 1 (1 Added, 1 Unchanged or only 1 Added).
int newEntryCount = db.ChangeTracker.Entries<MyEntity>().Count(e => e.State == System.Data.EntityState.Added);
db.SaveChanges();
}
顺便说一下,我使用的是Oracle DB,在我的EDMX文件中,我将autoincrement PK的“StoreGeneratedPattern”属性设置为“Identity”,并通过使用调用sequence.nextval()之前的insert触发器为插入的实体分配ID值。它们。
答案 0 :(得分:0)
DbSet.Add返回添加到DbSet的实体,也许它返回的是与传入的实例不同的实例。此外,SaveChanges返回什么?它应该返回添加,更新和删除的对象数。它是否与您尝试插入或更新的对象数相匹配?
“如果实体存在于excel工作表的多行中,那么我的最终List将具有同一实体的多个实例,每个实例的ID = 0。”
这也可能是一个问题。您说重复/共享行将获得ID为0的唯一实体实例。它们应该使用相同的实例。