EF Codefirst GET方法子模型不出现

时间:2019-05-17 11:16:35

标签: c# asp.net-core ef-code-first asp.net-core-webapi ef-database-first

EF Codefirst GET方法子模型不存在。 使用数据库优先,我想要以下Json结果。但是,我无法通过 Code First 获得以下Json。我需要一种结构来处理模型关系,而无需运行include方法。

Model.cs

        public class BloggingContext : DbContext
        {
            public BloggingContext(DbContextOptions<BloggingContext> options) : base(options){ }

            public virtual DbSet<Blog> Blogs { get; set; }
            public virtual DbSet<Post> Posts { get; set; }
        }

        public class Blog
        {
            public int BlogId { 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; }
        }

ValuesController.cs

        private readonly BloggingContext db;

        public ValuesController(BloggingContext db)
        {
            this.db = db;
        }

        // GET api/values
        [HttpGet]
        public ActionResult<IEnumerable<Blog>> Get()
        {
            return db.Blogs.ToList();
        }

Startup.cs

var connection = @"Server=(localdb)\mssqllocaldb;Database=EFGetStarted.AspNetCore.NewDb;Trusted_Connection=True;ConnectRetryCount=0";
            services.AddDbContext<Models.Model.BloggingContext>
                (options => options.UseSqlServer(connection));

数据库表

Blogs Table Result
__________________
BlogId  |   Url
1       |   asdasd1
2       |   asdas2

Posts Table Result
__________
PostId  |   Title   |   Content |   BlogId
1       |   asdasd  |   fdg     |   1
2       |   fsg     |   asda    |   1
3       |   dsgfsdg |   sgf     |   2

运行结果

[
  {
    "blogId": 1,
    "url": "asdasd1",
    "posts": null
  },
  {
    "blogId": 2,
    "url": "asdas2",
    "posts": null
  },
  {
    "blogId": 3,
    "url": "asdsad3",
    "posts": null
  }
]

我想使用以上代码

[
  {
    "blogId": 1,
    "url": "asdasd1",
    "posts": [
      {
        "PostId": 1,
        "Title": "asdasd",
        "Content": "fdg"
      },
      {
        "PostId": 2,
        "Title": "fsg",
        "Content": "asda"
      }
    ]
  },
  {
    "blogId": 2,
    "url": "asdas2",
    "posts": {
      "PostId": 2,
      "Title": "fsg",
      "Content": "asda"
    }
  },
  {
    "blogId": 3,
    "url": "asdsad3",
    "posts": null
  }
]

1 个答案:

答案 0 :(得分:0)

默认情况下,EF不会自动加载关系,因为这将需要SQL JOIN,这在大多数情况下都是不希望的-仅当您实际上想要相关数据时。

因此,您有两个选择:急于使用Include加载关系,或依靠延迟加载在访问时及时查询相关数据。延迟加载默认情况下未启用,因为坦率地说它有点反模式,除非您充分了解其影响和可能的问题,否则不应该使用它。

在这种特定情况下,那些可能出现的问题将迅速而戏剧性地抬起头来。由于您要对实体进行序列化,因此序列化程序将处理每个关系,从而导致单独发出查询以获取一组特定的相关数据。然后,您要遍历的每个博客也会发生这种情况。而且,如果任何相关项目本身具有相关的内容,那么您将要发出指数级的附加查询。简而言之,如果不同时执行数千个或更多查询,那么像这样的延迟加载可能会导致100条查询-至少您不想发生这种事情。

简而言之,您需要急切地加载您关心的关系,无论这是否是您的首选方法。这里没有免费的午餐。这是一个查询,一次包含所有联接,或者稍后对每个数据块进行大量查询。

或者,您可以考虑使用OData或GraphQL之类的东西。仅凭这一点并不能解决问题:默认情况下,不会包含相关项。但是,这两种功能都可以将相关数据作为请求的一部分进行请求,从而允许客户端仅检索他们需要或感兴趣的关系。这解决了您不希望一次指定和查询所有单个关系的问题,同时仍然为客户提供了在需要/需要时可以轻松获得的方法。