我创建了两个与我的两个类对应的列表:
//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();
这是为什么?我应该在每次修改数据库后保存更改吗?
答案 0 :(得分:0)
要避免此类问题,请设置实体之间的关系并使用这些关系,而不是尝试手动设置FK ID。像EF这样的ORM旨在为您解决这个问题,因此可以利用这种能力。
如果照片有评论,评论中有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。