0

データベースにインポートする必要があるデバイス、住所、および会社のデータ セットがありますが、新しいデータ セットに含まれる特定のデバイス/住所/会社がデータベースに既に含まれている可能性があります。その場合は、アドレスを除いて、データ セット内の新しい情報でそのエントリを更新する必要があります。そのアドレスの正確なコピーが存在するかどうかを確認し、存在しない場合は新しいエントリを作成します。

私の問題は、EF でデバイス/会社を取得しようとするのが非常に遅く、存在する場合は更新し、そうでない場合は挿入することです。これを修正するために、すべての会社、デバイス、およびアドレスを取得してそれぞれのハッシュマップに挿入し、新しいデータの識別子がハッシュマップに存在するかどうかを確認しようとしました。これにより、パフォーマンスが向上することはありませんでした。以下に私のコードを含めました。通常、私はバッチ挿入を行いますが、バッチ更新で何をするかはわかりません。誰かが別のルートをアドバイスできますか?

            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();
4

1 に答える 1

0

正確な問題はカバーされていませんが、このスレッドはデータベースのインポートのパフォーマンスを大幅に改善するのに役立ちました。読むことをお勧めします。

ハッシュが多い場合は、タスク並列ライブラリを使用すると役立つ場合があります。ID のマッピングにもハッシュ マップを使用していますが、これは非常に役立ちました。ただし、SaveChanges() をロックすることをお勧めします。これにより、同時実行の問題が発生しなくなります (このため、TPL はハッシュと変換を頻繁に行う場合にのみ役立ちます。この場合、TPL は非常に役立ちました。かなりの解析を行う必要がありました)。

于 2012-10-25T23:26:47.187 に答える