C# 将相同断开连接实体的不同实例插入实体框架
在我的MVC4项目中,我尝试将一些数据(从excel工作表填充)插入数据库Oracle 10g DB,使用12c ODAC和EF5 故事: 首先,我从excel中读取数据,然后将其转换为实体。但是excel数据没有主键ID列,我无法控制excel数据。因此,对于excel中的每一行,我首先在DB中搜索匹配项。如果存在匹配,我将使用DbContext获取匹配的实体。在这种情况下,实例化的类/实体已填充ID属性 另一方面,如果数据库中没有匹配项,我将实例化一个没有ID信息的实体类型的新类。如果实体存在于excel工作表的多行中,则我的最终列表将包含同一实体的多个实例,每个实例的ID均为0 填充数据后,我将实体逐个添加到DbContext中,并调用上下文的SaveChanges方法。然后,当我检查数据库时,我看到同一类的不同实例得到不同的ID,但这不是我想要的 我理解为什么会发生这种情况,因为如果未设置PK,DbContext无法关联类的不同实例。添加所有实体的EntityState: 我的问题是: 是否有一种方法可以告诉Entity Framework,如果一个实体的所有属性都彼此相等&&未设置PK/ID,则在插入数据库时将这些实体视为相同的实体 简化: 在以下代码中执行MyMethod后,我只希望在数据库表中创建一行数据:C# 将相同断开连接实体的不同实例插入实体框架,c#,entity-framework,asp.net-mvc-4,oracle10g,entity-framework-5,C#,Entity Framework,Asp.net Mvc 4,Oracle10g,Entity Framework 5,在我的MVC4项目中,我尝试将一些数据(从excel工作表填充)插入数据库Oracle 10g DB,使用12c ODAC和EF5 故事: 首先,我从excel中读取数据,然后将其转换为实体。但是excel数据没有主键ID列,我无法控制excel数据。因此,对于excel中的每一行,我首先在DB中搜索匹配项。如果存在匹配,我将使用DbContext获取匹配的实体。在这种情况下,实例化的类/实体已填充ID属性 另一方面,如果数据库中没有匹配项,我将实例化一个没有ID信息的实体类型的新类。如果实体存
// 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属性设置为标识,并通过使用在插入前调用sequence.nextval的触发器将ID值分配给插入的实体。DbSet.Add返回添加到DbSet的实体,可能它返回的实例与传入的实例不同。另外,SaveChanges返回什么?它应该返回添加、更新和删除的对象的列表。它是否与您尝试插入或更新的对象的类型匹配 如果实体存在于excel工作表的多行中,则我的最终列表将包含同一实体的多个实例,每个实例的ID均为0
这可能也是一个问题。您的意思是,重复/共享行将获得其自己的ID为0的唯一实体实例。他们应该使用相同的实例。我已经在做你所说的了。在常规列表中收集新实体,并针对每个新数据将数据与这些列表进行比较,每个excel行包含多个实体的信息,如果发现匹配项,则不在DbContext中再次添加实例。然而,我不喜欢这个解决方案,并试图找到一个简单的解决方案,EF处理这个逻辑。如果我找不到更优雅的方法,我将继续使用我的解决方案。