Запутанные статьи и документация о различиях (если таковые имеются) между системой.Данные.EntityState.Добавить & В Dbset.Добавлять
Я работаю над C# ASP.NET веб-приложение MVC 5 с EF 5. Отображение моих таблиц базы данных с помощью EF генерирует DbContext
класс а . Сегодня я читал отличная статья о создании общих классов DAL, но я остановился на следующей фразе:
обратите внимание, что использование метода ввода для изменения состояния объекта будет влияет только на фактическую сущность, которую вы передаете методу. Это не каскад через график и задать состояние всех связанных объектов, в отличие от в dbset.Метод add.
, что противоречит тому, что упоминается в этих вопросах:
- http://forums.asp.net/p/2015170/5803192.aspx
- http://forums.asp.net/p/2060606/5943259.aspx
- разница между DbSet.Добавить (сущность) и сущность.State = EntityState.Добавлено
- в чем разница между Идбсет.Добавить и DbEntityEntry.State = EntityState.Добавил?
в ответах на все вышеперечисленные вопросы все пользователи упомянули, что с помощью System.Data.EntityState.Added
точно так же, как с помощью DbSet.Add
. Но в статье, которую я упомянул сначала, говорится, что использование System.Data.EntityState.Added
не будет каскадировать через график.
основываясь на моем тесте, я заключаю, что использование System.Data.EntityState.Added
будет каскадировать через график так же, как в DBset.Add
случае. Статья неправильная, или это мой тест и Q&A?
2 ответов
эти методы те же, которые вы можете проверить регулярным тестированием, или, если вы хотите быть полностью уверены - некоторым исследованием кода EF 6.
-
DbSet.Add
метод (http://entityframework.codeplex.com/SourceControl/latest#src/EntityFramework/DbSet.cs)public virtual TEntity Add(TEntity entity) { Check.NotNull<TEntity>(entity, "entity"); this.GetInternalSetWithCheck("Add").Add((object) entity); return entity; }
это InternalSet<T>.Add(object)
метод.
-
DbEntityEntry<T>.State
собственность (http://entityframework.codeplex.com/SourceControl/latest#src/EntityFramework/Infrastructure/DbEntityEntry.cs)public EntityState State { get { return _internalEntityEntry.State; } set { _internalEntityEntry.State = value; } }
здесь _internalEntityEntry
из InternalEntityEntry
тип.
InternalEntityEntry.State
свойство (http://entityframework.codeplex.com/SourceControl/latest#src/EntityFramework/Internal/EntityEntries/InternalEntityEntry.cs)
public virtual EntityState State
{
get { return IsDetached ? EntityState.Detached : _stateEntry.State; }
set
{
if (!IsDetached)
{
if (_stateEntry.State == EntityState.Modified
&& value == EntityState.Unchanged)
{
// Special case modified to unchanged to be "reject changes" even
// ChangeState will do "accept changes". This keeps the behavior consistent with
// setting modified to false at the property level (once that is supported).
CurrentValues.SetValues(OriginalValues);
}
_stateEntry.ChangeState(value);
}
else
{
switch (value)
{
case EntityState.Added:
_internalContext.Set(_entityType).InternalSet.Add(_entity);
break;
case EntityState.Unchanged:
_internalContext.Set(_entityType).InternalSet.Attach(_entity);
break;
case EntityState.Modified:
case EntityState.Deleted:
_internalContext.Set(_entityType).InternalSet.Attach(_entity);
_stateEntry = _internalContext.GetStateEntry(_entity);
Debug.Assert(_stateEntry != null, "_stateEntry should not be null after Attach.");
_stateEntry.ChangeState(value);
break;
}
}
}
}
вы видите, что если сущность отсоединена (ваш случай) и состояние добавлено-то же самое InternalSet<T>.Add(object)
называется.
а для проверки путем испытаний:
using (var ctx = new TestDBEntities()) {
// just some entity, details does not matter
var code = new Code();
// another entity
var error = new Error();
// Code has a collection of Errors
code.Errors.Add(error);
var codeEntry = ctx.Entry(code);
// modify code entry and mark as added
codeEntry.State = EntityState.Added;
// note we did not do anything with Error
var errorEntry = ctx.Entry(error);
// but it is marked as Added too, because when marking Code as Added -
// navigation properties were also explored and attached, just like when
// you do DbSet.Add
Debug.Assert(errorEntry.State == EntityState.Added);
}
Я не знаю автора этого блога. Я знаю писателей книга DbContext хотя (хотя и не лично). Они знают EF наизнанку. Поэтому, когда на странице 80 они пишут
вызов
DbSet.Add
и параметрState
toAdded
оба достижения точно то же самое.
Я знаю, что делаю. Они делают то же самое, которая составляет:
если сущность не отслеживается контекст, он начнет отслеживаться контекстом в the
Added
государство. Оба!--1--> и параметрState
toAdded
операции с графами- это означает, что любые другие объекты, которые не отслеживаются контекстом и доступны от корневого объекта также будет отмечен какAdded
.
Я также знаю по опыту, что это работает именно так. Но чтобы устранить любые сомнения, в исходном коде EF оба DbSet.Add
и DbEntityEntry.State
(когда установлено значение Added
) приехать в то же самое точка в ObjectContext
это делает фактическую работу:
public virtual void AddObject(string entitySetName, object entity)
это функция, которая продолжает обманывать разработчиков, которые начинают работать с EF, как видно из большого количества вопросов в StackOverflow, задавая что-то вроде "как мои сущности дублируются?". Джули Лерман написала весь блог объясняя, почему это может произойти.
это продолжающееся заблуждение заставило команду EF принять решение изменить это поведение in ЭФ7.
возможно, автор блога, на который вы ссылаетесь, был одним из тех обманутых разработчиков.