2011-03-24 5 views
8

Я новичок в EF 4, и это то, что я сделал до сих пор:Вставить новый объект с существующим объектом

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

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

objectA.myObjectB = (objectB)cmbBObjects.selectedItem; 

Затем я создаю репозиторий для объекта A и вызываю метод сохранения. В этом сохранить метод у меня есть этот код ±

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?

ответ

17

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

  • нагрузки 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); 
+0

Спасибо. Я не понимаю предложения 1. Второе предложение: в репозитории объекта A сделайте что-то вроде: 'var obj = context.ObjectB.where (b => b.Id == objectA.myObjectB.Id) .firstOrDefault() ; context.ObjectA.Attach (OBJ); 'Это правильно? – Martijn

+0

Я отредактировал свой ответ. –

+0

@LadislavMrnka: Точно, все возможные варианты, и я полагаю, что второй вариант лучше всего для примера выше. +1 –

1

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

objectA.myObjectB = (objectB)cmbBObjects.selectedItem; 

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

1.Assign objectB идентификатор Objecta

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

2.Or нагрузки objectB из DataContext и чем назначить Objecta:

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

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

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

+0

objectA не имеет объектаB id напрямую, этот му st будет установлен следующим образом (я полагаю) 'objectA..myObjectB.Id = b.Id' Но, я думаю, это вызовет аргументNull exception, потому что свойство' .myObjectB' не установлено. Второе решение: я не думаю, что мне нужен мой контекст в winform, я хотел бы сохранить этот объект в своих репозиториях. – Martijn

+0

@Martijn: Хорошо, вам следует пойти вторым способом, предложенным мной (загрузить объект B из dataContext и назначить объекту A). –

Смежные вопросы