简体   繁体   中英

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.

Story:

First I read data from excel and then convert them to entities. However excel data has no Primary Key (ID) column (I DON'T HAVE CONTROL OVER EXCEL DATA). Therefore for every row in excel first I am searching DB for a match. If there is a match I am getting the matched entity by using the DbContext. In this case my instantiated class/entity has ID property filled.

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. 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.

After populating the data I add my entities to my DbContext one by one and call SaveChanges() method of the context. 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.

I understand why this is happening since DbContext cannot relate different instances of a class if the PK is not set. All entities's EntityState becomes Added :(

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?" .

Simplified:

After executing MyMethod() in below code, I want only one row of data created in my database Table:

// 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.

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? 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."

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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