1

I'm consuming a webservice which deserialises xml into model instances which are used to build the actual EF data models.

If I have this example class modelling a Property with a Branch:

public class Property
{
    public int Id {get; set;}

    public int Name {get; set;}

    public string BranchId {get; set;}

    [ForeignKey("BranchId")]
    public string Branch {get; set;}
}

If the Branch doesn't exist in the database, fine, EF inserts it. However, if it does, how can I instruct EF to update it instead?

I get from the examples, you Attach() an entity to a DbSet so that the framework knows not to insert it, but is there a way to do this auto-magically? e.g not have to write the bolierplate code which checks for the Branch everytime I insert a Property to know whether I need to Attach() it?

Phil Cooper
  • 3,083
  • 39
  • 63
  • 2
    What you're describing is an Upsert. I think this is a duplicate question. I'll flag it as such and provide a link there. – Necoras Sep 14 '16 at 20:14
  • 1
    Now if I knew it was labelled as `Upsert`, I might have found the answer without posting! Thanks for the link, very helpful. – Phil Cooper Sep 15 '16 at 06:17

1 Answers1

2
public Task Upsert(Property property)
{
    using (var context = new SomeDbContext())
    {
        //if the id is autoincrement field then you will need to pass the new id to the property if it changes.
        await Save(new Branch{ Id = property.BranchId, Name = property.Branch}, context);
        await Save(property, context);
        await context.SaveChangesAsync();
    }
}
private Task Save(Property property, SomeDbContext context)
{   
    var existingProperty = context.Property.FirstOrDefaultAsync(f => f.Id == property.Id);
    if (existingProperty == null)
    {
        context.Property.Add(property);
    }
    else
    {
        //maybe use automapper here if there is a lot of this stuff going on
        //EF is smart enough to figure out what needs updating and will write a terse update statment
        //no attach is needed since your existingProperty still exist within your context
        existingProperty.Name = property.Name;
        existingProperty.BranchId = property.BranchId;
        existingProperty.Branch = property.Branch;
    }

}
private Task Save(Branch branch, SomeDbContext context)
{   

    var existingBranch = context.Branch.FirstOrDefaultAsync(f => f.Id == branch.Id);
    if (existingBranch == null)
    {
        context.Branch.Add(branch);
    }
    else
    {
        existingBranch.Name = branch.Name;
    }
}

I hope I've understood your question... This is one of i guess many approaches. The benefit here is that your update statements are optimized by EF so that if only the 'Name' or 'Branch' changes then it will update those fields only. Anyway - I hope this helps.

Sooey
  • 39
  • 5
  • You have understood although I was after something that had less boiler plate code and something more generic, I appreciate your time adding this though. – Phil Cooper Sep 15 '16 at 06:16