简体   繁体   中英

Entity Framework query after AddObject

Last week I had a bug that I tried to recreate. A piece of existing code did a mass insert on the database. Though, a value was not allowed to be duplicate in the database The old code persisted the changes to the database after every AddObject with a SaveChanges. This was not performing very well. So, instead of saving it every time I saved it after every 1000 records (and did this in a transaction,but that is not relevant for this sample).

this code below gives a overview of what I did.

        TestEntities test = new TestEntities();

        for (int i = 0; i < 10; i++)
        {
            for (int j = 0; j < 10; j++)
            {
                string q = j.ToString();
                if (!test.warehouses.Any(x => x.combi == q))
                {
                    warehouse wh = new warehouse();
                    wh.combi = j.ToString();
                    wh.ean = j.ToString();
                    test.warehouses.AddObject(wh);
                }
            }

        }
        test.SaveChanges();

What I did not know was that entity framework only queries the data in the database and not the pending data so the any query gives no result on the database (and I was assuming that there would be a result.) Hence, this results in unwanted duplicates in the code above.

For now I solved it to store all soon to be added objects in memory and then store them in the database. This works, but gives a lot of overhead in the code. Is there a way to work around this issue? Can you tell EF to work on the database and the pending changes? Are all ORM's working like this?

Thanks, Patrick

Faced with similar problem I decided to check database as you do and check local data:

    if( !test.warehouses.Local.Any(x => x.combi == q ) 
        && !test.warehouses.Any(x => x.combi == q ) )

This should work.

Edit: But it doesn't. However, this does:

var isLocal = ( test as System.Data.Objects.ObjectContext ).ObjectStateManager
    .GetObjectStateEntries( System.Data.EntityState.Added )
    .Any( x => (x.Entity as warehouse).combi == q );
if( !isLocal && !test.warehouses.Any( x => x.combi == q ) ) {
    // ...
}

I have to note that IDbSet<> (used by my code first instead of ObjectSet<> created by model designer) has .Local property so there's no need to query ObjectStateManager. I know that code first is completely different thing but you can be very efficient with it, too: design database with Microsoft SQL Server Management Studio and run excellent Reverse Engineer Code First from Entity Framework Power Tools with default or customized (if needed) T4 templates to get almost anything. http://en.wiktionary.org/wiki/your_mileage_may_vary

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