简体   繁体   English

EF Core - 更新实体

[英]EF Core - Update Entity

I would like to update DB via Entity Framework Core Product Entity.我想通过实体框架核心产品实体更新数据库。

On each load a product I would like to increment a Visited number.在每次加载一个产品时,我想增加一个访问次数。

Product Context Class:产品上下文 Class:

[Table("product")]
public class Product
{
    [Key]
    [Column("id", TypeName = "int")]
    public int Id { get; set; }
    [Column("name")]
    public string Name { get; set; }
    [Column("active", TypeName = "bit")]
    public bool Active { get; set; }
    [Column("visited")]
    public int Visited { get; set; }

    // last group
    [Column("group_id")]
    public int GroupId { get; set; }
    [ForeignKey("GroupId")]
    public virtual Group Group { get; set; }

    // first group
    [Column("top_group_id")]
    public int? TopGroupId { get; set; }
    [ForeignKey("TopGroupId")]
    public virtual Group TopGroup { get; set; }

    // PN image
    [Column("file_image_id")]
    public int? ImageId { get; set; }

    [ForeignKey("ImageId")]
    public virtual File Image { get; set; }

    public virtual IEnumerable<ProductGrade> ProductGrades { get; set; }
    public virtual IEnumerable<ProductDescription> ProductDescriptions { get; set; }
    public virtual IEnumerable<ProductFile> ProductFiles { get; set; }
 }

In Controller, I call in CTOR _context:在 Controller 中,我调用了 CTOR _context:

// In class
private readonly ProductContext _context; 

// In method
var product = await _context.Products
                .OrderBy(b => b.Name)
                .Where(w => w.Name == model.Name)
                .Select(c => new ProductResDto
                {
                    Id = c.Id,
                    PartNumber = c.Name,
                    Group = c.Group.FullLink,
                    GroupId = c.GroupId,
                    Type = c.TopGroup.Name,
                    Image = new FileDto
                    {
                        Name = c.Image.Name,
                        GroupName = c.Image.FileGroup.Name,
                        Url = (c.Group.Top.Link != "/" ? c.Group.Top.Link : c.Group.Link) + "/pn/" + c.Image.Url,
                        Title = c.Image.Title,
                        Type = c.Image.FileType.MineType
                    }
                }).FirstAsync();

ProductResDto class:产品ResDto class:

public class ProductResDto
{
    [JsonIgnore] public int Id { get; set; }
    public string PartNumber { get; set; }
    public string Type { get; set; }
    public string Group { get; set; }
    [JsonIgnore] public int GroupId { get; set; }
    public ICollection<ParameterValueDto> Parameters { get; set; }
    public ICollection<ProductValueDto> Descriptions { get; set; }
    public ICollection<ProductValueDto> Grades { get; set; }
    public ICollection<FileGroupDto> Files { get; set; }
    public FileDto Image { get; set; }
    public ICollection<BreadCrumbDto> BreadCrumbs { get; set; }
    public RelatedProductResDto RelatedProducts { get; set; }
}

I would like to simply update product record like:我想简单地更新产品记录,例如:

var data = await _context.Products
            .OrderBy(b => b.Name)
            .Where(w => w.Name == model.Name && w.Active).FirstAsync();

        var product = new ProductResDto
        {
            Id = data.Id,
            PartNumber = data.Name,
            Group = data.Group.FullLink,
            GroupId = data.GroupId,
            Type = data.TopGroup.Name,
            Image = new FileDto
            {
                Name = data.Image.Name,
                GroupName = data.Image.FileGroup.Name,
                Url = (data.Group.Top.Link != "/" ? data.Group.Top.Link : data.Group.Link) + "/pn/" + data.Image.Url,
                Title = data.Image.Title,
                Type = data.Image.FileType.MineType
            }
        };

        data.Visited += 1;

        _context.Products.Update(data);
        await _context.SaveChangesAsync();

I got only Error because variable data has only raw data pro DB Product.我只得到错误,因为变量数据只有原始数据 pro DB Product。 Is there any better way how to do it easier?有没有更好的方法可以更轻松地做到这一点?

Like in the controller where I assign DB Context Class Product with all its dependencies to the ProductResDto?就像在 controller 中一样,我将数据库上下文 Class 产品及其所有依赖项分配给 ProductResDto?

Error:错误:

System.NullReferenceException: 'Object reference not set to an instance of an object.' System.NullReferenceException:“对象引用未设置为 object 的实例。”

In var product = new ProductResDto rowvar product = new ProductResDto

在此处输入图像描述

It loads only Product but without references, this is which I ask for simple way like in Controller where I use var product = await _context.Products它仅加载 Product 但没有引用,这是我要求的简单方法,例如在 Controller 中我使用var product = await _context.Products

Thank you for any help感谢您的任何帮助

You need to add .Include() statements, because without them, EF Core will not load the related properties Group , TopGroup and Image (this is known as Lazy Loading) and as you can see in the image, these properties are indeed null.您需要添加.Include()语句,因为没有它们,EF Core 将不会加载相关的属性GroupTopGroupImage (这称为延迟加载),并且如图所示,这些属性确实是 null。

It looks like you are also using deeper nested properties, which you can force to load using .ThenInclude() .看起来您也在使用更深层次的嵌套属性,您可以使用.ThenInclude()强制加载这些属性。

Here is how:方法如下:

var data = await _context.Products
    .Include(p => p.Group).ThenInclude(g => g.Top)
    .Include(p => p.TopGroup)
    .Include(p => p.Image).ThenInclude(i => i.FileGroup)
    .Include(p => p.Image).ThenInclude(i => i.FileType)
    .OrderBy(b => b.Name)
    .Where(w => w.Name == model.Name && w.Active)
    .FirstAsync();

It's possible that this example is not yet 100% complete, in that case you need to add further .Include and/or .ThenInclude statements.此示例可能尚未 100% 完成,在这种情况下,您需要添加更多.Include和/或.ThenInclude语句。

EF Core always analyzes the full LINQ query statement. EF Core 始终分析完整的 LINQ 查询语句。 Due to what is present in the .Select() statement in your first code block, EF Core sees that you want nested properties and it will create SQL that also loads these properties.由于第一个代码块中的.Select()语句中存在的内容,EF Core 会看到您需要嵌套属性,并将创建 SQL 来加载这些属性。 But if there is no .Select() to give EF Core this information, then you need to add .Include() statements + possibly also .ThenInclude() statements.但是,如果没有.Select()向 EF Core 提供此信息,那么您需要添加.Include()语句 + 可能还有.ThenInclude()语句。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM