Bulk einfügen und aktualisieren mit Entity Framework (Wahrscheinlich eine bessere alternative?)
Ich habe einen Datensatz von Geräten, Adressen und Unternehmen, die ich brauche, um den import in unsere Datenbank, mit der Sperrklinke, die in unserer Datenbank eventuell bereits über ein bestimmtes Gerät/Adresse/Firma enthalten ist, in das neue Daten-set. Wenn das der Fall ist, ich aktualisieren den Eintrag mit den neuen Daten in den Datensatz, ohne Adressen. Wir prüfen, ob eine exakte Kopie, die Adresse existiert, sonst machen wir einen neuen Eintrag.
Mein Problem ist, dass es sehr langsam ist, zu versuchen, schnappen Sie sich ein Gerät/Unternehmen in der EF und wenn es vorhanden ist, aktualisiert es, ansonsten einfügen. Um dies zu beheben habe ich versucht, alle Firmen, - Geräte und-Adressen und fügen Sie Sie in die jeweiligen hashmaps, und überprüfen Sie, ob der Bezeichner der neuen Daten in die hashmap. Dies hat nicht dazu geführt, dass ein performance-Steigerungen. Ich habe meinen code unten. In der Regel würde ich eine batch einfügen, ich bin mir nicht sicher, was ich tun würde, für ein batch-update aber. Kann jemand raten, eine andere route?
var context = ObjectContextHelper.CurrentObjectContext;
var oldDevices = context.Devices;
var companies = context.Companies;
var addresses = context.Addresses;
Dictionary<string, Company> companyMap = new Dictionary<string, Company>(StringComparer.OrdinalIgnoreCase);
Dictionary<string, Device> deviceMap = new Dictionary<string, Device>(StringComparer.OrdinalIgnoreCase);
Dictionary<string, Address> addressMap = new Dictionary<string, Address>(StringComparer.OrdinalIgnoreCase);
foreach (Company c in companies)
{
if (c.CompanyAccountID != null && !companyMap.ContainsKey(c.CompanyAccountID))
companyMap.Add(c.CompanyAccountID, c);
}
foreach (Device d in oldDevices)
{
if (d.SerialNumber != null && !deviceMap.ContainsKey(d.SerialNumber))
deviceMap.Add(d.SerialNumber, d);
}
foreach (Address a in addresses)
{
string identifier = GetAddressIdentifier(a);
if (!addressMap.ContainsKey(identifier))
addressMap.Add(identifier, a);
}
foreach (DeviceData.TabsDevice device in devices)
{
//update a device
Company tempCompany;
Address tempAddress;
Device currentDevice;
if (deviceMap.ContainsKey(device.SerialNumber)) //update a device
deviceMap.TryGetValue(device.SerialNumber, out currentDevice);
else //insert a new device
currentDevice = new Device();
currentDevice.SerialNumber = device.SerialNumber;
currentDevice.SerialNumberTABS = device.SerialNumberTabs;
currentDevice.Model = device.Model;
if (device.CustomerAccountID != null && device.CustomerAccountID != "")
{
companyMap.TryGetValue(device.CustomerAccountID, out tempCompany);
currentDevice.CustomerID = tempCompany.CompanyID;
currentDevice.CustomerName = tempCompany.CompanyName;
}
if (companyMap.TryGetValue(device.ServicingDealerAccountID, out tempCompany))
currentDevice.CompanyID = tempCompany.CompanyID;
currentDevice.StatusID = 1;
currentDevice.Retries = 0;
currentDevice.ControllerFamilyID = 1;
if (currentDevice.EWBFrontPanelMsgOption == null) //set the Panel option to the default if it isn't set already
currentDevice.EWBFrontPanelMsgOption = context.EWBFrontPanelMsgOptions.Where( i => i.OptionDescription.Contains("default")).Single();
//link the device to the existing address as long as it is actually an address
if (addressMap.TryGetValue(GetAddressIdentifier(device.address), out tempAddress))
{
if (GetAddressIdentifier(device.address) != "")
currentDevice.Address = tempAddress;
else
currentDevice.Address = null;
}
else //insert a new Address and link the device to it (if not null)
{
if (GetAddressIdentifier(device.address) == "")
currentDevice.Address = null;
else
{
tempAddress = new Address();
tempAddress.Address1 = device.address.Address1;
tempAddress.Address2 = device.address.Address2;
tempAddress.Address3 = device.address.Address3;
tempAddress.Address4 = device.address.Address4;
tempAddress.City = device.address.City;
tempAddress.Country = device.address.Country;
tempAddress.PostalCode = device.address.PostalCode;
tempAddress.State = device.address.State;
addresses.AddObject(tempAddress);
addressMap.Add(GetAddressIdentifier(tempAddress), tempAddress);
currentDevice.Address = tempAddress;
}
}
if (!deviceMap.ContainsKey(device.SerialNumber)) //if inserting, add to context
{
oldDevices.AddObject(currentDevice);
deviceMap.Add(device.SerialNumber, currentDevice);
}
}
context.SaveChanges();
Du musst angemeldet sein, um einen Kommentar abzugeben.
Obwohl es doesn ' T decken Sie Ihre genaue problem, dieser thread hat mir geholfen, verbessern die performance meiner Datenbank zu importieren ungemein und ich empfehle Ihnen es zu Lesen.
Wenn Sie eine Menge von hashing mit der task parallel library helfen könnte. Wir verwenden auch hash-maps zu Zuordnungs-IDs und es hat mir sehr geholfen. Aber ich empfehle Ihnen, lock{} auf die SaveChanges(), so dass Sie nicht laufen in der concurrency-Probleme (weil es die TPL nur hilft, wenn man hash und konvertieren eine Menge - in unserem Fall half eine ganze Menge, denn wir hatten ziemlich viel zu tun der Parsen).