Чистый способ обработки циркулярных ссылок в EF? - программирование
Подтвердить что ты не робот

Чистый способ обработки циркулярных ссылок в EF?

Скажем, у меня есть эта структура таблицы:

Client
-----------
ClientId                     int            not null    (identity)
CurrentDemographicId         int            null        (FK to ClientDemographic)
OtherClientFields            varchar(100)   null


ClientDemographic
------------------
ClientDemographicId          int            not null    (identity)
ClientId                     int            not null    (FK to Client)
OtherClientDemographicFields varchar(100)   null

Идея заключается в том, что Client (в EF) будет иметь список ClientDemographics и свойство CurrentDemographic.

Проблема заключается в том, когда я настраиваю структуру объекта и пытаюсь его сохранить, я получаю эту ошибку:

Невозможно определить действительное упорядочение для зависимых операций. Зависимости могут существовать из-за ограничений внешнего ключа, требований к модели или сохраненных в магазине значений.

Эта ошибка имеет смысл. У меня есть круговая ссылка в моей настройке таблицы. Он не знает, какой объект вставить сначала (потому что он одновременно должен иметь идентификатор из обеих таблиц).

Итак, я взломал решение, которое выглядит так:

// Save off the unchanged ClientDemograpic
ClientDemographic originalClientDemographic = client.CurrentClientDemographic;

// Merge the contract into the client object
Mapper.Map(contract, client);

// If this is a new client then add as new to the list.
if (client.ClientId == 0)
{
    dataAccess.Add(client);
}

// Restore the original ClientDemographic so that EF will not choke
// on the circular reference.
ClientDemographic newClientDemographic = null;
if (client.CurrentClientDemographic != originalClientDemographic)
{
    newCurrentClientDemographic = client.CurrentClientDemographic;
    client.CurrentClientDemographic = originalClientDemographic;
}

// save our changes to the db.
dataAccess.SaveChanges();

// Restore updates to ClientDemographics and save (if needed)
if (newClientDemographic != null)
{
    client.CurrentClientDemographic = newCurrentClientDemographic;
    dataAccess.SaveChanges();
}

Но изменение ссылки обратно на предыдущее значение, сохранение, а затем установка его снова, чтобы я мог снова сохранить, чувствует себя как хак.

Есть ли более чистый способ справиться с циклическими ссылками в EF?

4b9b3361

Ответ 1

Я бы сказал, что ответ: "Не совсем". Единственный чистый способ справиться с круговой ссылкой - снова взглянуть на дизайн и удалить его.

В этом случае - приближаясь к нему с точки зрения Domain Driven Design - я бы сказал, что Client - это корень вашего агрегата, а ClientDemographic - объект значения; ClientDemographics определяются значениями их "Другие поля ClientDemographic". Поэтому вы можете удалить ClientId из ClientDemographic, и проблема не будет устранена.

Тем не менее, если вы решились на эту структуру, то, к сожалению, я не думаю, что там есть аккуратный способ обработки в EF, no.

Изменить. Чтобы дать Client multiple ClientDemographics, а также свойство CurrentClientDemographic, вы можете пойти другим путем; удалите CurrentClientDemographicId из Client и добавьте двоичное поле IsCurrent к ClientDemographic. Затем EF дает вам свойство коллекции ClientDemographics, и вы можете добавить следующее в новый, неполный класс:

public partial class Client
{
    public ClientDemographic CurrentDemogaphic
    {
        get { return this.ClientDemographics.First(cd => cd.IsPrimary); }
    }
}

Ответ 2

Простым способом избежать этой ошибки является создание первичного объекта сначала, SaveChanges, а затем создание зависимого объекта перед вызовом SaveChanges снова.

В этом случае сначала создайте Client, SaveChanges, затем создайте объект ClientDemographic, добавьте его в коллекцию и снова установите в качестве CurrentDemographic, а затем SaveChanges.