EF - Сохранение нового объекта со связанными существующими объектами, создавая дубликаты - PullRequest
1 голос
/ 20 июля 2011
public class Car {
    public string SomeProperty { get; set; }
    public Manufacturer Manufacturer { get; set; }
    public IList<Color> Colors { get; set; }
}

public class Manufacturer { 
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Color { 
    public int Id { get; set; }
    public string Name { get; set; }
}

У меня уже есть таблицы, полные цветов и производителей. Когда я создаю новый автомобиль, я хочу иметь возможность назначить ему цвет и производителя, привязанные к .net MVC.

Когда я сохраняю свою новую машину с

context.Cars.Add(car);

Создается новый автомобиль (отлично), но также создаются новый цвет и производитель, даже если для этих объектов уже были установлены идентификаторы и имена, соответствующие содержимому базы данных.

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

* * 1010

Либо загрузить производителя и цвет из EF, а затем связать их с автомобилем вместо использования объектов, привязанных к MVC.

car.Manufacturer = carRepository.GetManufacturer(car.Manufacturer.Id);
car.Colors = carRepository.GetColorsById(car.Colors);

Я не в восторге ни от одного решения, так как этот пример очень тривиален, но мои реальные дела намного сложнее. Я действительно не хочу подробно разбираться с EF для каждого сохраняемого объекта. У меня есть много сложных графов объектов для сохранения, и это кажется очень подверженным ошибкам.

Есть ли способ заставить EF вести себя более похоже на NHibernate, когда вы можете дать ему что-то с уже назначенным идентификатором, и он без вашего вмешательства будет предполагать, что он уже существует?

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

Ответы [ 2 ]

1 голос
/ 20 июля 2011

К сожалению, EF не имеет ничего похожего на session.Load в NHibernate, который позволяет вам получить прокси из идентификатора.

Обычный способ справиться с этим в EF - создать отдельное поле FK, содержащее скалярное значение, соответствующее ссылке. Например:

public virtual Manufacturer Manufacturer { get; set; }
public int ManufacturerId { get; set; }

Тогда вам нужно только установить ManufacturerId, и он будет сохранен правильно.

(Так много для "POCO" и "сначала код". Пфффффф)

0 голосов
/ 20 июля 2011

Вы можете определить скалярные свойства в ваших сущностях и привязать к ним значения. Например добавить ManufacturerId и ColorId

public class Car {
    public string SomeProperty { get; set; }
    public int? ManufacturerId { get; set; }
    public virtual Manufacturer Manufacturer { get; set; }
    public int? ColorId { get; set; }
    public virtual Color Color { get; set; }
}

Затем установите эти скалярные свойства при назначении (например, через DropDownList)

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

...