«Произошла ошибка при обновлении записей» в EF, когда я пытаюсь сохранить SaveChanges () в контекст - PullRequest
0 голосов
/ 26 мая 2018

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

//Photo
        var photos = new List<Photo>{
            new Photo {
                Title = "Title1",
                Description = "Description1",
                CreatedDate = DateTime.Today
            }
        };

        //Comment
        var comments = new List<Comment>
        {
            new Comment{
                PhotoId = 1,
                UserName = "User1",
                Subject = "Comment1",
            }
        };

Когда я попытался добавить эти два списка в свой объект контекста, а затем в SaveChanges, я получил сообщение об ошибке:

photos.ForEach(s => context.Photos.Add(s));
comments.ForEach(s => context.Comments.Add(s));

context.SaveChanges();

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

        photos.ForEach(s => context.Photos.Add(s));
        context.SaveChanges();

        comments.ForEach(s => context.Comments.Add(s));
        context.SaveChanges();

Почему это так?Должен ли я сохранять изменения после каждой модификации моей БД?

1 Ответ

0 голосов
/ 26 мая 2018

Чтобы избежать подобных проблем, установите отношения между вашими сущностями и используйте эти отношения, а не пытайтесь устанавливать идентификаторы FK вручную.ORM, такие как EF, разработаны для того, чтобы проработать эту деталь для вас, поэтому используйте эту возможность.

Если на фотографии есть комментарии, где комментарий имеет столбец PhotoID, тогда настройте объекты примерно так:

public class Photo
{
   public int PhotoID {get; set;}
   public string Title {get; set;}
   public string Description {get; set;}

   private List<Comment> _comments = new List<Comment>();
   public virtual List<Comment> Comments 
   {
      get {return _comments;}
      set {_comments = value;}
   }
}

public class Comment
{
   public string UserName {get; set;}
   public string Subject {get; set;}
}

Обратите внимание, что я не добавил PhotoID для комментариев.Если вы хотите искать комментарии, например, и переходить обратно к фотографии, вы можете добавить:

public virtual Photo Photo {get; set;}

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

Чтобы настроить эти свойства навигации, чтобы EF мог ими управлять, я использую сопоставления EntityTypeConfiguration.Существуют также методы, использующие аннотации данных, но я считаю, что ETConfigs более надежен.

public class PhotoConfiguration : EntityTypeConfiguration<Photo>
{
   public PhotoConfiguration()
   {
      ToTable("Photos");
      HasKey(x => x.PhotoID)
         .Property(x => x.PhotoID)
         .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); // This informs EF that the database will be assigning the PK.

      HasMany(x => x.Comments)
         .WithRequired()
         .Map(x => x.MapKey("PhotoID")); // This tells EF to join comments to a Photo /w the PhotoID on the Comment table. HasMany says a Photo has many comments, and WithRequired() points to a non-nullable FK on Comment, but no navigation property coming back to Photo.
   }
}

Этот пример для EF6, для EFCore вы можете заменить вызов .Map () / w

.HasForeignKey("PhotoID");

, который выполнит то же самое со свойством shadow.Если вы хотите указывать ссылку на фотографию в каждом комментарии, вы можете добавить виртуальное свойство в комментарий, а затем заменить .WithRequired() на .WithRequired(x => x.Photo), и это установит связь.

public class CommentConfiguration : EntityTypeConfiguration<Comment>
{
   public CommentConfiguration()
   {
      ToTable("Comments");
      HasKey(x => x.CommentID)
         .Property(x => x.CommentD)
         .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 
   }
}

Сейчасесли вы хотите сохранить фотографию и комментарий:

   var photo = new Photo 
   {
      Title = "Title1",
      Description = "Description1",
      CreatedDate = DateTime.Today,
      Comments = new[] 
      {
         New Comment { UserName = "User1", Subject = "Comment1" }
      }.ToList()
   };
   context.Photos.Add(photo);
   context.SaveChanges();

Обратите внимание, что мы не сохраняем комментарии отдельно.EF управляет всеми PK / FK за кулисами.После SaveChanges мы можем извлечь PK наших сущностей из свойств сущности.

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