簡體   English   中英

EF Core 5.0 - 更新多對多實體 ASP.NET Core Web API

[英]EF Core 5.0 - Updating many-to-many entities in ASP.NET Core Web API

EF Core 5.0 引入了多對多關系。 我對如何通過我的 asp .net api 更新它們感到困惑。

對於一對一和一對多關系,有一種約定,只需添加屬性名稱后跟 ID。

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    public BlogImage BlogImage { get; set; }
}

public class BlogImage
{
    public int BlogImageId { get; set; }
    public byte[] Image { get; set; }
    public string Caption { get; set; }

    public int BlogId { get; set; }
    public Blog Blog { get; set; }
}

所以適當的 POST 請求看起來像

{
  "BlogId": 123,
  "Url": "example.com",
  "BlogImageID": 42
}

但我無法確定是否存在約定或多對多關系的外觀

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public ICollection<Tag> Tags { get; set; }
}

public class Tag
{
    public string TagId { get; set; }

    public ICollection<Post> Posts { get; set; }
}

map http 對使用 EF 5.0 的多對多關系請求的正文是否存在約定?

考慮以下兩個處於多對多關系的實體 -

public class Post
{
    public int Id { get; set; }
    public string Title { get; set; }

    public ICollection<Tag> Tags { get; set; }
}

public class Tag
{
    public int Id { get; set; }
    public string Name { get; set; }

    public ICollection<Post> Posts { get; set; }
}

在更新Post實體中的Tags時,在最常見的情況下,從客戶端發送一個新的 tag Id列表,請求有效負載將如下所示 -

{
    "id": 123,
    "title": "An Awesome Post",
    "tags": [2, 7, 13]
}

通常,您希望定義一個 DTO 來表示此請求 object,例如 -

public class PostUpdateDTO
{
    public int Id { get; set; }
    public string Title { get; set; }

    public List<int> Tags { get; set; }
}

然后,對於更新操作本身,您可以執行類似 -

[HttpPut]
public async Task Put([FromBody]PostUpdateDTO dto)
{
    // fetch existing Post including related Tags
    var post = await _DbCtx.Posts
        .Include(p => p.Tags)
        .FirstOrDefaultAsync(p => p.Id == dto.Post.Id);

    // remove all Tags from the existing list
    post.Tags.Clear();
    
    // add new Tags to the list whose Ids are sent by the client
    // but to identify them you need the list of all available tags
    var availableTags = await _DbCtx.Tags.ToListAsync();
    foreach (var id in dto.Tags)
    {
        post.Tags.Add(availableTags.First(p => p.Id == id));
    }
    
    // modify properties of Post if you need, like -
    // post.Title = dto.Title;

    await _DbCtx.SaveChangesAsync();
}

如您所見,這需要訪問數據庫以獲取所有可用Tag的列表。 如果您不喜歡它並想跳過它,您可以嘗試以下方法 -

[HttpPut]
public async Task Put([FromBody]PostUpdateDTO dto)
{
    // fetch existing Post including related Tags
    var post = await _DbCtx.Posts
        .Include(p => p.Tags)
        .FirstOrDefaultAsync(p => p.Id == dto.Post.Id);

    // remove Tags which are in the existing Tag list, but not 
    // in the new list sent by the client
    post.Tags.Where(tag => !dto.Tags.Any(id => id == tag.Id))
        .ToList().ForEach(tag => post.Tags.Remove(tag));

    // add Tags which are in the new list sent by the client, but 
    // not in the existing Tag list
    dto.Tags.Where(id => !post.Tags.Any(tag => tag.Id == id))
        .ToList().ForEach(id => post.Tags.Add(new Tag { Id = id }));

    // modify properties of Post if you need, like -
    // post.Title = dto.Title;

    await _DbCtx.SaveChangesAsync();
}

關於那個 -屬性名稱后跟 ID
您所指的那種 Id 屬性代表外鍵。 這兩個實體都不包含外鍵屬性,因為它們都不依賴於另一個。 外鍵表示父/子或委托人/依賴關系。 但是當兩個實體處於多對多關系時,它們是相互獨立的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM