开发者

Entity Framework - Avoiding child duplicates if they are not persited yet

开发者 https://www.devze.com 2023-03-22 13:07 出处:网络
Actually I use DbContext, but I just tested it with ObjectContext as well. // Engine 1 Engine engine = new Engine();

Actually I use DbContext, but I just tested it with ObjectContext as well.

// Engine 1
Engine engine = new Engine();
Manufacturer manufacturer = new Manufacturer();

engine.Manufacturer = manufacturer;

// Engine 2
engine = new Engine();
engine.Manufacturer = manufacturer // Engine 2 has the same manufacturer like Engine 1

context.SaveChanges();

I use identity columns (int), where new IDs are generated. In debug mode I see that the ID for engine is "0". Well, if I implement context.SaveChanges right after the Engine 1 block, the new manufacturer is being saved to DB. With EntityKey or Any check, I can reference the new manufacturer to Engine 2 without any problems. But without immediate SaveChanges(), two entries of same manufacturer are being saved to DB (the code above). Is EF unable to reference internally like normal objects? As you see above, manufacturer is one and the same object, so I wonder if it's possible to obtain a successfull insert without pre-save the child/manufacturer.

EDIT: I think I found the problem

MachineEntities context = new MachineEntities();
        context.Configuration.AutoDetectChangesEnabled = true;

        // Engine 1
        Engine engine1 = new Engine();
        engine1.Name = "engine1";

        Manufacturer manufacturer = new Manufacturer();
        manufacturer.Name = "manufacturer1";

        engine1.Manufacturer = manufacturer;

        // Engine 2
        Engine engine2 = new Engine();
        engine2.Name = "engine2";

        manufacturer = new Manufacturer();
        manufacturer.Name = "manufacturer1";

        engine2.Manufacturer = manufacturer;


        // Add Engine 1

        if (context.Manufacturers.Any(m => m.Name == engine1.Manufacturer.Name))
        {
            // The manufacturer's name is identical, so use the one in the context instead the assigned one.
            engine1.Manufacturer = context.Manufacturers.Single(m => m.Name == engine1.Manufacturer.Name);
        }
        else
        {
            // The manufacturer is not known, add it to the context
            context.Set<Manufacturer>().Add(engine1.Manufacturer);
        }

        // Add Engine 2


        if (context.Manufacturers.Any(m => m.Name == engine1.Manufacturer.Name))
        {
            // The manufacturer's name is identical, so use the one in the context instead the assigned one.
            engine2.Manufacturer = context.Manufacturers.Single(m => m.Name == engine2.Manufacturer.Name);
        }
        else
        {
            context.Manufacturers.Add(engine2.Manufacturer);
        }

        context.SaveChanges();

        context.Dispose();

"Any" or any comparison won't give me any results. It only gives me those entities, which are already persisted in DB, but not the fresh new added ones. So it's duplicated. The local ones are ignored as I see in debugger, and the one in "Result View" are the one, where the command is executed a开发者_开发技巧gainst. So the new added entities are located in "Manufacturers.Local".


I just tried the following:

var a1 = new Activity{WorkflowId = 1, Title = "test"};
var a2 = new Activity{WorkflowId = 1, Title = "test2"};
var d = new WorkflowDisplay{WorkflowId = 1, Title = "Test"};
a1.WorkflowDisplay = d;
a2.WorkflowDisplay = d;
// Any of the next three lines can be commented out, but if
// they are all commented, nothing happens.
AddToWorkflowDisplays(d);
AddToActivities(a1);
AddToActivities(a2);
SaveChanges();

... and I only saw a single WorkflowDisplay added. So I'm pretty sure this has something to do with your specific implementation. Have you overridden the GetHashCode or Equals methods of any of your entities, or done any similar sort of customization of the auto-generated code?

0

精彩评论

暂无评论...
验证码 换一张
取 消