Bulk inserting and updating with Entity Framework (Probably a better alternative?)

Posted by Dave on Stack Overflow See other posts from Stack Overflow or by Dave
Published on 2012-10-25T22:56:26Z Indexed on 2012/10/25 23:00 UTC
Read the original article Hit count: 244

I have a data set of devices, addresses, and companies that I need to import into our database, with the catch that our database may already include a specific device/address/company that is included in the new data set. If that is the case, I need to update that entry with the new information in the data set, excluding addresses. We check if an exact copy of that address exists, otherwise we make a new entry.

My issue is that it is very slow to attempt to grab a device/company in EF and if it exist updated it, otherwise insert it. To fix this I tried to get all the companies, devices, and addresses and insert them into respective hashmaps, and check if the identifier of the new data exists in the hashmap. This hasn't led to any performance increases. I've included my code below. Typically I would do a batch insert, I'm not sure what I would do for a batch update though. Can someone advise a different 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();

© Stack Overflow or respective owner

Related posts about c#

Related posts about entity-framework