EF4 - POCO - SaveChanges неожиданно дублирует элементы в таблице поиска - PullRequest
1 голос
/ 29 октября 2010

Я использую EF4 с POCO, и код ниже - это то, что я должен обновить лицензию.Я только вставил сюда раздел кода, который имеет отношение к проблеме, который добавляет LicenseDetails.

Проблема заключается в том, что для каждого вставленного LicenseDetail EF также неожиданно добавляет строки в таблицу поиска "Item".Почему?!

Взаимосвязь обеих таблиц, определенных в базе данных (SQLServer 2008), показана ниже, и сначала я делаю базу данных, поэтому EF создает отношения сущностей на основе этого.* метод обновления:

    public static void UpdateLicense(License license)
    {
        using (ALISEntities context = new ALISEntities())
        {
            context.ContextOptions.ProxyCreationEnabled = true;

            var storedLicense = 
                context.Licenses.Include("LicenseDetails")
                .Where(o => o.Id == license.Id).SingleOrDefault();

            //////////////////////////////////////////////////////////////
            // license details to add
            List<LicenseDetail> toAdd = new List<LicenseDetail>();

            foreach (LicenseDetail ld in license.LicenseDetails)
            {
                if (storedLicense.LicenseDetails
                    .Where(d => d.ItemId == ld.ItemId).Count() == 0)
                {
                    toAdd.Add(ld);
                }
            }

            toAdd.ForEach(i => storedLicense.LicenseDetails.Add(i));

            context.SaveChanges();
        }
    }

Ответы [ 2 ]

0 голосов
/ 29 октября 2010

В итоге мне пришлось выдать context.ObjectStateManager.ChangeObjectState (d.Item, EntityState.Unchanged) для каждого добавленного LicenseDetail.Это решило проблему.

0 голосов
/ 29 октября 2010

Когда вы добавляете новый LicenseDetails в контекст, вы также добавляете элементы, на которые ссылаются эти LicenseDetails. Поскольку контекст не знает, что Предметы уже существуют в базе данных, он добавляет их. Вы должны сообщить контексту, что Предметы уже находятся в базе данных, вызывая context.Items.Attach (licenseDetail.Item).

Вы также можете попробовать использовать

context.Licenses.Include("LicenseDetails").Find(license.Id);

вместо

context.Licenses.Include("LicenseDetails")
                .Where(o => o.Id == license.Id).SingleOrDefault();

и вообще нет необходимости использовать список добавлений - просто продолжайте добавлять licenseDetails в первом цикле foreach.

...