我有一个简单的项目来显示问题,我想将 ICollection<Post>
与视图 View_BlogPosts
连接起来。这只是简化的场景,在现实生活中,我需要将实体与大视图连接起来,其中包含来自不同表的许多列。
代码中最有趣的部分是:OnModelCreating(ModelBuilder modelBuilder)
,其中有配置视图和实体:Post
(一个博客到多个帖子)。但它现在不起作用,这行代码:var test = db.BlogWithPosts.ToList();
返回空的 Posts 集合。
如何解决这个问题?
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace Samples
{
public class Program
{
private static void Main()
{
SetupDatabase();
using (var db = new BloggingContext())
{
var test = db.BlogWithPosts.ToList();
}
}
private static void SetupDatabase()
{
using (var db = new BloggingContext())
{
if (db.Database.EnsureCreated())
{
db.Blogs.Add(
new Blog
{
Name = "Fish Blog",
Url = "http://sample.com/blogs/fish",
Posts = new List<Post>
{
new Post { Title = "Fish care 101" },
new Post { Title = "Caring for tropical fish" },
new Post { Title = "Types of ornamental fish" }
}
});
db.Blogs.Add(
new Blog
{
Name = "Cats Blog",
Url = "http://sample.com/blogs/cats",
Posts = new List<Post>
{
new Post { Title = "Cat care 101" },
new Post { Title = "Caring for tropical cats" },
new Post { Title = "Types of ornamental cats" }
}
});
db.Blogs.Add(
new Blog
{
Name = "Catfish Blog",
Url = "http://sample.com/blogs/catfish",
Posts = new List<Post>
{
new Post { Title = "Catfish care 101" }, new Post { Title = "History of the catfish name" }
}
});
db.SaveChanges();
db.Database.ExecuteSqlRaw(
@"CREATE VIEW View_BlogPosts AS
SELECT b.Name , b.BlogId, b.Url FROM Blogs b");
}
}
}
}
public class BloggingContext : DbContext
{
private static readonly ILoggerFactory _loggerFactory
= LoggerFactory.Create(
builder => builder.AddConsole().AddFilter((c, l) => l == LogLevel.Information && !c.EndsWith("Connection")));
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
public DbSet<BlogWithPosts> BlogWithPosts { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.UseSqlServer(
// @"Server=(localdb)\mssqllocaldb;Database=Sample.KeylessEntityTypes;Trusted_Connection=True;ConnectRetryCount=0;")
@"Server=.\SQLEXPRESS;Database=test_view;Trusted_Connection=True;")
.UseLoggerFactory(_loggerFactory);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<BlogWithPosts>(eb =>
{
//eb.HasNoKey();
eb.ToView("View_BlogPosts");
eb.HasKey(bwp => bwp.BlogId);
eb.Property(v => v.BlogName).HasColumnName("Name");
eb
.HasMany(bwp => bwp.Posts)
.WithOne()
.HasForeignKey(p => p.BlogId);
});
}
}
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public ICollection<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
}
public class BlogWithPosts
{
public int BlogId { get; set; }
public string BlogName { get; set; }
public ICollection<Post> Posts { get; set; } = new List<Post>();
}
}
编辑:
感谢@Neil W 的回答:
这是个好点,但在 var test = db.BlogWithPosts.Include(bwp => bwp.Posts).ToList();
之后仍然没有帖子。
我在运行程序后检查了数据库,在 Post 表中我发现添加了第二个 Id:BlogId1
我像这样填充了与 BlogId
相同的 BlogId1
列:
和帖子出现
但是如何设置第二个id:BlogId1
不会出现。
答案 0 :(得分:2)
访问上下文时需要询问相关实体,使用Include:
var test = db.BlogWithPosts.Include(bwp => bwp.Posts).ToList();
答案 1 :(得分:0)
感谢所有回答和评论。正如@atiyar 指出的那样,Post
和 Blog
之间应该有明确的关系,这会停止创建 BlogId1
列。所以工作示例如下:
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace Samples
{
public class Program
{
private static void Main()
{
SetupDatabase();
using (var db = new BloggingContext())
{
var test = db.BlogWithPosts.Include(bp => bp.Posts).ToList();
}
}
private static void SetupDatabase()
{
using (var db = new BloggingContext())
{
if (db.Database.EnsureCreated())
{
db.Blogs.Add(
new Blog
{
Name = "Fish Blog",
Url = "http://sample.com/blogs/fish",
Posts = new List<Post>
{
new Post { Title = "Fish care 101" },
new Post { Title = "Caring for tropical fish" },
new Post { Title = "Types of ornamental fish" }
}
});
db.Blogs.Add(
new Blog
{
Name = "Cats Blog",
Url = "http://sample.com/blogs/cats",
Posts = new List<Post>
{
new Post { Title = "Cat care 101" },
new Post { Title = "Caring for tropical cats" },
new Post { Title = "Types of ornamental cats" }
}
});
db.Blogs.Add(
new Blog
{
Name = "Catfish Blog",
Url = "http://sample.com/blogs/catfish",
Posts = new List<Post>
{
new Post { Title = "Catfish care 101" }, new Post { Title = "History of the catfish name" }
}
});
db.SaveChanges();
db.Database.ExecuteSqlRaw(
@"CREATE VIEW View_BlogPosts AS
SELECT b.Name , b.BlogId, b.Url FROM Blogs b");
}
}
}
}
public class BloggingContext : DbContext
{
private static readonly ILoggerFactory _loggerFactory
= LoggerFactory.Create(
builder => builder.AddConsole().AddFilter((c, l) => l == LogLevel.Information && !c.EndsWith("Connection")));
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
public DbSet<BlogWithPosts> BlogWithPosts { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.UseSqlServer(
// @"Server=(localdb)\mssqllocaldb;Database=Sample.KeylessEntityTypes;Trusted_Connection=True;ConnectRetryCount=0;")
@"Server=.\SQLEXPRESS;Database=test_view;Trusted_Connection=True;")
.UseLoggerFactory(_loggerFactory);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<BlogWithPosts>(eb =>
{
//eb.HasNoKey();
eb.ToView("View_BlogPosts");
eb.HasKey(bwp => bwp.BlogId);
eb.Property(v => v.BlogName).HasColumnName("Name");
eb
.HasMany(bwp => bwp.Posts)
.WithOne()
.HasForeignKey(p => p.BlogId);
});
modelBuilder.Entity<Blog>(blog =>
{
blog.HasMany(bwp => bwp.Posts)
.WithOne(b => b.Blog)
.HasForeignKey(p => p.BlogId);
});
}
}
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public ICollection<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
public Blog Blog { get; set; }
}
public class BlogWithPosts
{
public int BlogId { get; set; }
public string BlogName { get; set; }
public ICollection<Post> Posts { get; set; } = new List<Post>();
}
}
此示例在 EF Core 5.0.2 上测试的重要意义