2015-04-17 6 views
0

У меня очень простой Entity с 4 полями: Имя, штат, город и идентификатор и некоторые валидации.EF DbSet.Find() возвращает Отсоединенный объект

[Table("Places")] 
public class Place : BindableBase, IDataErrorInfo 
{ 
    private string name; 
    private string city; 
    private Estado state; 
    private int id; 

    [Required] 
    [StringLength(500)]   
    public string Name 
    { 
     get { return this.name; } 
     set { SetProperty(ref name, value); } 
    } 

    [Required] 
    [StringLength(500)] 
    public string City 
    { 
     get { return this.city; } 
     set { SetProperty(ref city, value); } 
    } 

    [Required]   
    public State State 
    { 
     get { return this.state; } 
     set { SetProperty(ref state, value); } 
    } 

    [Key] 
    public int Id 
    { 
     get { return this.id; } 
     set { SetProperty(ref id, value); } 
    } 

    [NotMapped] 
    public bool IsValid 
    { 
     get 
     { 
      return Validator.TryValidateObject(this, new ValidationContext(this), new Collection<ValidationResult>(), true); 
     } 
    } 

    #region IDataErrorInfo Members 
    /// <summary> 
    /// IDataErrorInfo Interface Error Message for the object. 
    /// </summary> 
    [NotMapped] 
    public string Error 
    { 
     get { throw new NotImplementedException(); } 
    } 

    public string this[string propertyName] 
    { 
     get 
     { 
      var context = new ValidationContext(this) 
      { 
       MemberName = propertyName 
      }; 

      var results = new Collection<ValidationResult>(); 
      bool isValid = Validator.TryValidateObject(this, context, results, true); 

      if (!isValid) 
      { 
       ValidationResult result = results.SingleOrDefault(p => 
                    p.MemberNames.Any(memberName => 
                        memberName == propertyName)); 

       return result == null ? null : result.ErrorMessage; 
      } 

      return null; 
     } 
    } 
    #endregion 
} 

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

Я использую:

public void UpdatePlace(Place place) 
{ 
    var entity = context.Places.Find(place.Id); 

    if (entity == null) 
    { 
     throw new InvalidOperationException("Place not found."); 
    } 

    context.Entry(place).CurrentValues.SetValues(place); 
    context.SaveChanges(); 
} 

Когда я получаю

context.Entry(place).CurrentValues.SetValues(place); 

я получаю исключение, как:

System.InvalidOperationException

« 'CurrentValues' Member не может быть вызван для объекта типа «Место», потому что сущность не существует в контексте. Чтобы добавить объект в контекст вызова Добавить или Attach метод из DbSet.»

context.Entry показывает мне, что на самом деле объект отсоединяется

context.Entry shows detached

Но документация DbSet.Find() метода ясно показывает, что Find() должен вернуть прикрепленную единицу в случае, если один найден в БД:

Находит объект с заданными значениями первичного ключа. Если в контексте существует сущность с указанными значениями первичного ключа, она немедленно возвращается без запроса в хранилище. В противном случае в хранилище делается запрос для объекта с указанными значениями первичного ключа, и этот объект , если он найден, прикреплен к контексту и возвращается. Если ни один объект не найден в контексте или в хранилище, возвращается значение null.

Так что, когда я пытаюсь получить CurrentValues, так как объект отсоединяется, он бросает Exception ... но, насколько я понимаю, там должен быть присоединен объект, или ноль, а не что-нибудь еще .. ..

Я ничего не могу найти об этой ошибке в Интернете, я использую SQL CE 4.0 в качестве базы данных, кто-нибудь знает, что происходит?

Я думаю, что я могу только Attach сущность каждый раз, когда получаю ее от Find, но все же хочу понять, что происходит с моим программным обеспечением, поскольку этого не должно происходить.

ответ

1

Я думаю, вы должны просто изменить эту строку:

context.Entry(entity).CurrentValues.SetValues(place); 
+0

Хорошо ... Теперь я чувствую себя тупой хахаха, я получил этот код из учебника, я бы заплатил больше внимания на копии + пасты , и учебник полностью ошибочен, я сообщу об этом автору. Большое спасибо ErikEJ! https://www.youtube.com/watch?v=7SwgqLJCLI8 код показан в 6:30 видео. – mFeinstein

+0

4:00 минут на самом деле. – mFeinstein

+0

Просто, чтобы добавить, он сделал модульные тесты, поэтому, очевидно, этот код был «доверенным» ....Наверное, это отличный урок о тестах .... – mFeinstein