Вставить новый объект с существующим объектом - PullRequest
8 голосов
/ 24 марта 2011

Я новичок в EF 4, и это то, что я сделал до сих пор:

  • Создать файл edmx на основе моей базы данных
  • Создать генерацию кода для моих объектов (POCO). Теперь у меня есть model1.tt, когда развернут, я вижу все свои классы
  • Создать репозиторий для каждого класса на основе IRepository

Теперь я работаю с двумя объектами, A и B. Объект A имеет свойство типа B. В моей winform форме у меня есть комбо, заполненное объектами типа B. Когда нажата кнопка сохранения, новый экземпляр Класс A создан, и все свойства установлены. Свойство объекта B устанавливается следующим образом:

objectA.myObjectB = (objectB)cmbBObjects.selectedItem;

Затем я создаю хранилище для objectA и вызываю метод save. В этом методе сохранения у меня есть этот код ±

public bool Save(ObjectA obj)
{
  using(MyContext context = new MyContext())
  {
    context.objectAs.AddObject(obj);
    context.SaveChanges();
  }
}

Этот код сохраняет новую запись в базе данных, но он также создает новую запись для объекта B! Я не хочу этого, потому что объект B уже существует в базе данных! (Я выбрал этот в выпадающем списке).

Вот как я заполняю свой комбинированный список:

В хранилище objectB:

public IList<ObjectB> GetAll()
{
    using(MyContext context = new MyContext())
    {
        IList<ObjectB> objects = context.objectBs.ToList();
        return objects;
    }
}

В моем виде:

ObjectBRepository rep = new ObjectBRepository();
IList<ObjectB> objects = rep.GetAll;

cmbBObjects.Datasource = objects;
// etc..

Итак, мой вопрос: что мне нужно сделать, чтобы сохранить объект A без создания новой записи для объекта B?

Ответы [ 2 ]

19 голосов
/ 24 марта 2011

Если вы не хотите вставлять objectB, вы должны сообщить об этом EF.Когда вы звоните context.objectAs.AddObject(obj) для objectA, вы говорите: Я хочу вставить объект A и все его зависимости .Но очевидно, что вы не хотите сохранять зависимости, поэтому вы должны либо:

  • загрузить objectB из БД, прежде чем добавить его в objectA.В таком случае EF будет знать, что objectB является существующим объектом, и не будет вставлять его снова.
  • Присоедините objectB к контексту перед добавлением его в objectA.ObjectB будет обработан как существующий, но без изменений.
  • Установите состояние objectB после вставки objectA.Вы можете сделать это, позвонив по номеру: context.ObjectStateManager.ChangeObjectState(objectB, EntityState.Unchanged)

Пример первого предложения:

var id = objectB.Id;
objectA.myObjectB = context.ObjectBs.SingleOrDefault(o => o.Id == id);

Пример второго предложения:

context.ObjectBs.Attach(objectB);
objectA.myObjectB = objectB;

Примертретьего предложения:

objectA.myObjectB = objectB;
context.ObjectAs.AddObject(objectA);
context.ObjectStateManager.ChangeObjectState(objectB, EntityState.Unchanged);
1 голос
/ 24 марта 2011

Я полагаю, что проблема в следующей строке:

objectA.myObjectB = (objectB)cmbBObjects.selectedItem;

Из-за результата (objectB)cmbBObjects.selectedItem отсоединено от структуры сущностей datacontext, создайте новый экземпляр.Вместо этого вы можете:

1. Назначить идентификатор объекта B для объекта A

var b = (objectB)cmbBObjects.selectedItem;
objectA.myObjectBId = b.Id;

2. Или загрузить объект B из dataContext и затем присвоить объекту A:

var b = (objectB)cmbBObjects.selectedItem;
var dcB = context.ObjectBs.Single(x=> x.Id == b.Id);
objectA.myObjectB = dcB;

Простопопробуй мои предложения и вернись с результатами, потому что я точно не знаю.

Надеюсь, что это поможет.

...