Vraag EntityFramework, invoegen indien niet bestaat, anders bijwerken


Ik heb een Entity-Set-land, dat een databasetabel '<' char (2), char (3), nvarchar (50> in mijn database weergeeft.

Ik heb een parser die een land [] -array van geparseerde landen retourneert en problemen ondervindt met het op de juiste manier bijwerken. Wat ik wil is: Neem de reeks landen, want die landen die nog niet in de database zijn, voegen ze toe, en die bestaande update als er velden anders zijn. Hoe kan dit worden gedaan?

void Method(object sender, DocumentLoadedEvent e)
{
    var data = e.ParsedData as Country[];
    using(var db = new DataContractEntities)
    {
       //Code missing


    }
}

Ik dacht zoiets als

for(var c in data.Except(db.Countries)) but it wount work as it compares on wronge fields.

Ik hoop dat iemand eerder deze problemen heeft gehad en een oplossing voor mij heeft. Als ik het object Land niet kan gebruiken en een array van deze eenvoudig kan invoegen / bijwerken, zie ik niet veel profijt van het gebruik van het framework, omdat van uitvoerders ik denk dat het sneller is om een ​​aangepast SQL-script te schrijven dat ze invoegt in plaats van automatisch te controleren of een land staat het al in de database voordat u het invoegt?

Oplossing

Zie in plaats daarvan antwoord van bericht.

Ik voegde override aan mijn landklasse toe:

    public partial class Country
{

    public override bool Equals(object obj)
    {
        if (obj is Country)
        {
            var country = obj as Country;
            return this.CountryTreeLetter.Equals(country.CountryTreeLetter);
        }
        return false;
    }
    public override int GetHashCode()
    {
        int hash = 13;
        hash = hash * 7 + (int)CountryTreeLetter[0];
        hash = hash * 7 + (int)CountryTreeLetter[1];
        hash = hash * 7 + (int)CountryTreeLetter[2];
        return hash;
    }
}

en deed toen:

        var data = e.ParsedData as Country[];
        using (var db = new entities())
        {
            foreach (var item in data.Except(db.Countries))
            {
                db.AddToCountries(item); 
            }
            db.SaveChanges();
        }

22
2017-08-06 10:34


oorsprong


antwoorden:


Ik zou het eenvoudig doen:

void Method(object sender, DocumentLoadedEvent e)
{
    var data = e.ParsedData as Country[];
    using(var db = new DataContractEntities)
    {
        foreach(var country in data)
        {
            var countryInDb = db.Countries
                .Where(c => c.Name == country.Name) // or whatever your key is
                .SingleOrDefault();
            if (countryInDb != null)
                db.Countries.ApplyCurrentValues(country);
            else
                db.Countries.AddObject(country);
        }
        db.SaveChanges();
     }
}

Ik weet niet hoe vaak uw toepassing dit moet uitvoeren of hoeveel landen uw wereld heeft. Maar ik heb het gevoel dat dit niets is waar je moet denken aan geavanceerde prestatie-optimalisaties.

Bewerk

Alternatieve benadering die maar één vraag zou uitbrengen:

void Method(object sender, DocumentLoadedEvent e)
{
    var data = e.ParsedData as Country[];
    using(var db = new DataContractEntities)
    {
        var names = data.Select(c => c.Name);
        var countriesInDb = db.Countries
            .Where(c => names.Contains(c.Name))
            .ToList(); // single DB query
        foreach(var country in data)
        {
            var countryInDb = countriesInDb
                .SingleOrDefault(c => c.Name == country.Name); // runs in memory
            if (countryInDb != null)
                db.Countries.ApplyCurrentValues(country);
            else
                db.Countries.AddObject(country);
        }
        db.SaveChanges();
     }
}

24
2017-08-06 11:37



De moderne vorm, met gebruik van latere EF-versies zou zijn:

context.Entry(record).State = (AlreadyExists ? EntityState.Modified : EntityState.Added);
context.SaveChanges();

AlreadyExists kan komen door de sleutel te controleren of door de database te doorzoeken om te zien of het item al bestaat.


7
2018-02-06 17:31



U kunt uw eigen implementeren IEqualityComparer<Country> en geef dat door aan de Except() methode. Ervan uitgaande dat uw land-object heeft Id en Name eigenschappen, een voorbeeld van die implementatie zou er als volgt kunnen uitzien:

public class CountryComparer : IEqualityComparer<Country>
{
    public bool Equals(Country x, Country y)
    {
        return x.Name.Equals(y.Name) && (x.Id == y.Id);
    }

    public int GetHashCode(Country obj)
    {
        return string.Format("{0}{1}", obj.Id, obj.Name).GetHashCode();
    }
}

en gebruik het als

data.Countries.Except<Country>(db, new CountryComparer());

Hoewel het in uw geval lijkt alsof u alleen nieuwe objecten moet extraheren, kunt u gebruiken var newCountries = data.Where(c => c.Id == Guid.Empty); als uw ID Guid is.

De beste manier is om de Country.EntityState eigendom en voer daar acties uit met betrekking tot waarde (Vrijstaand, Gewijzigd, Toegevoegd, etc.)

U moet meer informatie verstrekken over wat uw data collectie bevat d.w.z. de Land-objecten opgehaald uit een database via het entiteitsframework, in welk geval hun context kan worden gevolgd, of genereert u ze op een andere manier.


0
2017-08-06 10:48



Ik ben niet zeker dat dit de beste oplossing zal zijn, maar ik denk dat je alle landen uit DB moet halen en het vervolgens met je geparseerde gegevens moet controleren

 void Method(object sender, DocumentLoadedEvent e)
 {
    var data = e.ParsedData as Country[];
    using(var db = new DataContractEntities)
    {
       List<Country> mycountries = db.Countries.ToList();
       foreach(var PC in data)
       {
          if(mycountries.Any( C => C.Name==PC.Name ))
          {
             var country = mycountries.Any( C => C.Name==PC.Name );
             //Update it here
          }
          else
          {
               var newcountry = Country.CreateCountry(PC.Name);//you must provide all required parameters
               newcountry.Name = PC.Name;
               db.AddToCountries(newcountry)
          }
       }
       db.SaveChanges();
   }
  }

0
2017-08-06 10:53