user1077685
user1077685

Reputation:

Upsert with composite key?

Using EF6.1, I'm working with a table with a composite key as below:

enter image description here

How can I run an upsert method using Entity Framework?

I've written the following method but I've read that it should not be used for upserts, only migrations (please disregard the design pattern for now):

public void UpsertNumberOfMarkets(List<Entities.NumberOfMarkets> marketsList)
{
    using (MyDbContext db = new MyDbContext())
    {
        foreach (var market in marketsList)
        {
            db.NumberOfMarkets.AddOrUpdate(market);
        }
    }
}

I'm also not certain that it works correctly. Any thoughts? I'd like to avoid deleting and inserting as we have an audit logging table for updates.

EDIT: I've written the following method which may handle this - is this the preferred approach?

public void UpsertNumberOfMarkets(List<Entities.NumberOfMarkets> marketsList)
{
    using (MyDbContext db = new MyDbContext())
    {
        foreach (var market in marketsList)
        {
            var predicate = PredicateBuilder.True<Entities.NumberOfMarkets>();
            predicate = predicate.And(n => n.ProjectId == market.ProjectId);
            predicate = predicate.And(n => n.Year == market.Year);

            var existingMarketEntry = db.NumberOfMarkets.AsExpandable().Where(predicate).FirstOrDefault();

            if (existingMarketEntry != null)
                existingMarketEntry.Markets = market.Markets;
            else
            {
                db.NumberOfMarkets.Add(market);
            }
        }
        db.SaveChanges();
    }
}

Upvotes: 0

Views: 657

Answers (1)

Jags
Jags

Reputation: 782

Yes.AddOrUpdate should only be used for migrations for below reason

It Updates all the values which are provided but mark all other values as NULL (which are not provided) which may not be the behaviour we want in real world application.

In your case you can follow below steps

using (MyDbContext db = new MyDbContext())
        {
            foreach (var market in marketsList)
            {
                var existingMarket =
                    db.Markets.FirstOrDefault(x => x.ProjectID == market.ProjectID && x.Year == market.Year);
                if (existingMarket != null)
                {
                    //Set properties for existing market
                     existingMarket.Year == market.Year
                     //etc
                }
                else
                {

                    db.Markets.Add(market);
                }
                db.SaveChanges();
            }
        }

Upvotes: 1

Related Questions