简体   繁体   English

将相同的断开实体的不同实例插入实体框架

[英]Inserting different instances of same Disconnected Entities into Entity Framework

In my MVC4 project, I am trying to insert some data, that I populated from an excel worksheet, into database (Oracle 10g DB using 12c ODAC) by using EF5. 在我的MVC4项目中,我尝试使用EF5将从excel工作表填充的一些数据插入数据库(使用12c ODAC的Oracle 10g DB)中。

Story: 故事:

First I read data from excel and then convert them to entities. 首先,我从excel中读取数据,然后将它们转换为实体。 However excel data has no Primary Key (ID) column (I DON'T HAVE CONTROL OVER EXCEL DATA). 但是,excel数据没有“主键(ID)”列(我无法控制EXCEL数据)。 Therefore for every row in excel first I am searching DB for a match. 因此,对于excel中的每一行,我首先在DB中搜索匹配项。 If there is a match I am getting the matched entity by using the DbContext. 如果有匹配项,我将使用DbContext获得匹配的实体。 In this case my instantiated class/entity has ID property filled. 在这种情况下,我实例化的类/实体具有ID属性。

On the other hand, if there is no match in the DB I am instantiating a new class of entity type without an ID information. 另一方面,如果数据库中没有匹配项,我将实例化没有ID信息的新的实体类型类。 If entity exists in more than one row of excel worksheet then my final List would have more than one instance of the same entity each have ID = 0. 如果实体存在于多于一行的excel工作表中,则我的最终列表将具有多个相同实体的实例,每个实例的ID = 0。

After populating the data I add my entities to my DbContext one by one and call SaveChanges() method of the context. 填充数据后,我将我的实体一一添加到我的DbContext中,并调用上下文的SaveChanges()方法。 Then when I check the Database I see that different instances of the same class getting different IDs, but this is not what I want. 然后,当我检查数据库时,我看到同一类的不同实例获得了不同的ID,但这不是我想要的。

I understand why this is happening since DbContext cannot relate different instances of a class if the PK is not set. 我理解为什么会这样,因为如果未设置PK,DbContext无法关联类的不同实例。 All entities's EntityState becomes Added :( 所有实体的EntityState变为已添加:(

My question is: 我的问题是:

"Is there a way to tell Entity Framework that if "all the properties of an entity are equal to each other && the PK/ID is not set" treat these entities as same entities when inserting into database?" “是否有一种方法可以告诉实体框架,如果“一个实体的所有属性彼此都相等且&/未设置PK / ID”,则在插入数据库时​​将这些实体视为相同的实体?” .

Simplified: 简化:

After executing MyMethod() in below code, I want only one row of data created in my database Table: 在下面的代码中执行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();
}

By the way I am using an Oracle DB and in my EDMX file I set "StoreGeneratedPattern" attribute of autoincrement PK as "Identity" and assigning ID values to inserted entities by using before insert triggers which calls sequence.nextval() in them. 顺便说一下,我正在使用Oracle数据库,并且在我的EDMX文件中,将自动增量PK的“ StoreGeneratedPattern”属性设置为“ Identity”,并通过在插入触发器之前使用插入的触发器(在其中调用sequence.nextval())为它们分配ID值。

DbSet.Add returns the entity that was added to the DbSet, maybe it's returning a different instance than the one passed in. Also, what does SaveChanges return? DbSet.Add返回添加到DbSet的实体,也许它返回的实例与传入的实例不同。而且,SaveChanges返回什么? It's supposed to return the # of objects added, updated and deleted. 应该返回添加,更新和删除的对象数。 Does it match the # of objects you're trying to insert or update? 它是否与您要插入或更新的对象数匹配?

"If entity exists in more than one row of excel worksheet then my final List would have more than one instance of the same entity each have ID = 0." “如果实体存在于多于一行的excel工作表中,那么我的最终列表将具有多个相同实体的实例,每个实例的ID =0。”

That is also probably a problem. 那可能也是一个问题。 You're saying duplicate/shared rows will get their own unique entity instance with an ID of 0. They should be using the same instance. 您说重复/共享的行将获得其自己的唯一实体实例,其ID为0。它们应使用相同的实例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM