我在UWP中遇到efcore问题。我想为每个请求使用一个DbContext,因为它似乎是使用efcore的最佳方式。但是当我尝试添加包含现有实体的新实体时,我的问题就出现了。例如: 我有一个包含帖子列表的博客。所以,帖子包含一个Blog实例。 假设我添加了一个博客。之后当我尝试添加一个新帖子并添加博客作为Blog时,我有一个SQLiteException:
SQLite错误19:'UNIQUE约束失败:Blogs.BlogId'
那么防止这个问题的最佳方法是什么?
我在github上发布了一个示例项目here
在此示例中,添加博客然后添加帖子,应该发生错误。
这是代码的最小部分:
博客模型:
class Post
{
public int PostId { get; set; }
public string Message { get; set; }
public int BlogId { get; set; }
public Blog Blog { get; set; }
}
发布模型:
class EfCoreTesterContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite("Data Source=efcoretester.sqlite");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Post>()
.HasOne(x => x.Blog)
.WithMany(x => x.Posts)
.HasForeignKey(x => x.BlogId);
}
}
DbContext:
class DataAccessService
{
#region Singleton
public static DataAccessService Instance { get; } = new DataAccessService();
#endregion
#region Constructors
private DataAccessService()
{
}
#endregion
#region Public methods
public void AddBlog(Blog blog)
{
using (var db = new EfCoreTesterContext())
{
db.Add(blog);
db.SaveChanges();
}
}
public List<Blog> GetBlogs()
{
using (var db = new EfCoreTesterContext())
{
return db.Blogs.Include(x => x.Posts).ToList();
}
}
public void AddPost(Post post)
{
using (var db = new EfCoreTesterContext())
{
db.Add(post);
db.SaveChanges();
}
}
public List<Post> GetPosts()
{
using (var db = new EfCoreTesterContext())
{
return db.Posts.ToList();
}
}
#endregion
}
数据访问方法:
Asp.net
答案 0 :(得分:3)
添加包含其他现有实体的新实体时的UWP efcore问题
根据您的代码段,该模型显示Blog
和Post
之间的一对多关系。 Post
是依赖实体,Blog
是主体。
由于Post.BlogId
是外键,因此当您要使用现有Post
添加Blog
实例时,应将现有Blog.BlogId
添加到外键列拥有外键约束。因此,要添加包含现有Post
的新Blog
,您应该更新添加新的Post
部分,如下所示:
private async void btnAddPost_Click(object sender, RoutedEventArgs e)
{
if (!string.IsNullOrEmpty(txtPostMessage.Text))
{
Blog exsitblog = lvBlogs.SelectedItem as Blog;
var newPost = new Post() { Message = txtPostMessage.Text, BlogId = exsitblog.BlogId };
//var newPost = new Post() { Message = txtPostMessage.Text, Blog = lvBlogs.SelectedItem as Blog };
DataAccessService.Instance.AddPost(newPost);
txtPostMessage.Text = string.Empty;
lvPosts.Items.Add(newPost);
}
else
{
MessageDialog dialog = new MessageDialog("Please enter post name");
await dialog.ShowAsync();
}
}
您的原始代码行用于创建一个引用了新Post
实体的新Blog
实体,以便在您向Blog
表添加相同记录时抛出异常。添加新的Post
时引用的新Blog
应如下所示:
private async void btnAddPost_Click(object sender, RoutedEventArgs e)
{
if (!string.IsNullOrEmpty(txtPostMessage.Text))
{
Blog withnewblog = new Blog()
{
BlogId = 5,
Name = "test"
};
var newPost = new Post() { Message = txtPostMessage.Text, Blog = withnewblog };
DataAccessService.Instance.AddPost(newPost);
txtPostMessage.Text = string.Empty;
lvPosts.Items.Add(newPost);
}
else
{
MessageDialog dialog = new MessageDialog("Please enter post name");
await dialog.ShowAsync();
}
}
答案 1 :(得分:1)
对于您的后续问题,目前我们有三个表格,Person
,Blog
和Post
。 Person
到Post
和Blog
到Post
都是一对多的关系。如何添加记录?
在这种情况下,Post
应包含两个外键。因此,由外键约束引起,每当您有一条新的Post
记录时,您应该分配引用的Blog
以及Person
。
为此,您可以考虑这一点,添加Blog
条记录,然后添加Person
条记录,现在我们可以依赖添加现有BlogId
和{{1}的新帖子作为外键。
在这种情况下,是否有必要在Blog.Posts列表和Owner.Posts列表中添加我的新帖子?
因此,对于此问题,当您使用PersonId
添加新帖时,您必须同时指定一个现有的Blog
。并且您无法在没有存在Person
的帖子中添加Blog
,反之亦然。您不需要再次将帖子列表添加到引用的Person
,因为您已经强制将它们分配给帖子。