简体   繁体   English

如何仅使用数据库中的实体框架支架模型

[英]How to work only with the Entity Framework Scaffolded Models from Database

I have been working with .Net Core Entity Framework database first approach with the Scaffolding technique. 我一直在使用带有脚手架技术的.Net Core Entity Framework数据库第一种方法。

It generated me a couple Models/Classes from my Database Tables, but for now, I will just minimize the issue I am having to this two tables... a relation one to many on the both ChampionID column: 它从数据库表中生成了几个模型/类,但是现在,我将这两个表的问题减至最少...两个ChampionID列上的一对多关系:

在此处输入图片说明

So, after scaffolding/mapping the models with EntityCore Tools it generated the following two classes (and several others that are not relevant): 因此,在使用EntityCore Tools脚手架/映射模型之后,它生成了以下两个类(以及其他几个不相关的类):

Champion.cs: Champion.cs:

public partial class Champion
{
    public Champion()
    {
        ChampionScreenshot = new HashSet<ChampionScreenshot>();
        ChampionUser = new HashSet<ChampionUser>();
        ChampionUserRate = new HashSet<ChampionUserRate>();
    }

    public int ChampionId { get; set; }
    public string Name { get; set; }
    public string Nickname { get; set; }
    public string Description { get; set; }
    public string ImagePath { get; set; }
    public byte AttackDamageScore { get; set; }
    public byte AbilityPowerScore { get; set; }
    public byte ResistanceScore { get; set; }
    public byte PlayingDifficult { get; set; }
    public int PrimaryClassId { get; set; }
    public int SecondaryClassId { get; set; }

    public ChampionClass PrimaryClass { get; set; }
    public ChampionClass SecondaryClass { get; set; }
    public ICollection<ChampionScreenshot> ChampionScreenshot { get; set; }
    public ICollection<ChampionUser> ChampionUser { get; set; }
    public ICollection<ChampionUserRate> ChampionUserRate { get; set; }
}

ChampionScreenshot.cs: ChampionScreenshot.cs:

public partial class ChampionScreenshot
{
    public int ChampionScreenshotId { get; set; }
    public string ImagePath { get; set; }
    public int ChampionId { get; set; }

    public Champion Champion { get; set; }
}

My doubt is: what is the correct way to retrieve a Champion object with the ChampionScreenshot attribute filled? 我的疑问是:检索带有ChampionScreenshot属性填充的Champion对象的正确方法是什么?

For example, this is what I am doing in my Service layer: 例如,这就是我在服务层中所做的事情:

    public async Task<Champion> GetChampion(int id)
    {
        Champion champion = await _context.Champion.FirstAsync(m => m.ChampionId == id);
        champion.ChampionScreenshot = _context.ChampionScreenshot.ToListAsync().Result.FindAll(m => m.ChampionId == champion.ChampionId);

        return champion;
    } 

So I am basically getting a specific Champion and then filling the ChampionScreenshot attribute (which is also a Class) separately, but the thing is that inside my ChampionScreenshot there is also a Champion class attribute which fully loads once again: 所以我基本上是得到一个特定的Champion,然后分别填充ChampionScreenshot属性(也是Class),但事实是,我的ChampionScreenshot中还有一个Champion类属性,可以再次完全加载:

在此处输入图片说明

Which is obviously generating an error once it is exposed in the endpoint of the Restful Service: 一旦将其暴露在Restful Service的端点中,显然会产生错误:

[Produces("application/json")]
[Route("api/Champions")]
public class ChampionsController : Controller
{
    [HttpGet("{id}")]
    public async Task<IActionResult> GetChampion([FromRoute] int id)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        var champion = await _service.GetChampion(id);

        if (champion == null)
        {
            return NotFound();
        }
        return Ok(champion);
    }
    ...

Error: 错误:

Newtonsoft.Json.JsonSerializationException: Self referencing loop detected for property 'champion' with type 'ChampionsService.Models.Champion'. Path 'championScreenshot[0]'. 

So, I was thinking in just creating my custom model and fill it with the data extracted from my DbContext instead of returning the models already created but I really think that there should be a way to fully use only the mapped Models, I was wondering that... 因此,我在考虑只创建自定义模型并用从DbContext中提取的数据填充它,而不是返回已经创建的模型,但是我真的认为应该有一种方法可以仅使用映射的模型,我想知道...

Champion references itself: Champion称呼自己:

Champion > multiple ChampionScreenshot > Champion (back to the original object) 冠军>多个冠军屏幕截图>冠军(返回原始对象)

That's easy to solve: 这很容易解决:

return Json(champion, new JsonSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore });

Or you could do it for the entire application: 或者您可以对整个应用程序执行此操作:

services.AddMvc().AddJsonOptions(opts => 
{
    opts.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});

And then just: 然后:

return Json(champion);

The following troubles me, though: 但是,以下问题困扰着我:

Champion champion = await _context.Champion.FirstAsync(m => m.ChampionId == id);
champion.ChampionScreenshot = _context.ChampionScreenshot.ToListAsync().Result.FindAll(m => m.ChampionId == champion.ChampionId);

You are saying "go to the database, download every single championscreenshot and find the ones I want through an in-memory search". 您说的是“转到数据库,下载每个冠军屏幕快照,然后通过内存搜索找到我想要的屏幕快照”。 That's not only horrible slow, it also wastes a lot of resources in your application and in the database. 这不仅令人震惊,而且还浪费了应用程序和数据库中的大量资源。 For including data, you use Include : 要包含数据,请使用Include

Champion champion = await _context.Champion
    .Include(x => x.ChampionScreenshot)
    .FirstAsync(x => x.ChampionId == id);

(this says "go to the database and bring me the champion but also include all the ChampionScreenshot that correspond, through an inner join). (这表示“进入数据库并带给我冠军,但也通过内部联接包括所有对应的ChampionScreenshot)”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在Entity Framework中先从数据库更新元数据模型不起作用 - Metadata updating models from database first in Entity Framework does not work 如何仅获取特定表以使用 C# 中的 Entity Framework Core 从数据库创建模型 - How to get only specific tables to create models from database with Entity Framework Core in C# 在Entity Framework 6.0中从数据库更新模型 - Updating models from database in Entity Framework 6.0 实体框架数据库优先从基类继承模型 - Entity Framework Database First inherits models from base class 其中具有List &lt;&gt;的模型..实体框架如何工作? - Models with List<> in them .. How does this work with Entity Framework? 脚手架实体框架 DeletePersonalData 不起作用 onclick - Scaffolded Entity Framework DeletePersonalData not working onclick 是否可以使用实体框架数据库优先方法从数据库表创建的模型之外创建视图模型? - Is it possible to create view models by out of models created from database tables using entity framework DB first approach? 实体框架代码第一个数据库未与模型同步 - Entity Framework code first database not synced with models 在实体框架中处理更新模型并与数据库同步 - Handling update models and synchronizes with database in entity framework 数据库更改后更新实体框架模型 - Updating Entity Framework Models after database change
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM