gpt4 book ai didi

asp.net - 添加标签来讨论 Entity Framework 中的多对多关系

转载 作者:行者123 更新时间:2023-12-02 10:08:43 25 4
gpt4 key购买 nike

我正在创建一个 API 端点,该端点创建一个新的对话,其中包含应与该对话关联的标签。我在我的域中的标签和对话之间设置了多对多关系,请参阅下面的关系。

标签.cs

using System;
using System.Collections.Generic;

namespace Conferency.Domain
{
public class Tag : IAuditable
{
public int Id { get; set; }
public string Name { get; set; }
public List<TalkTag> TalkTags { get; set; }
public DateTime ModifiedAt { get; set; }
public DateTime CreatedAt { get; set; }
}
}

Talk.cs

using System;
using System.Collections.Generic;

namespace Conferency.Domain
{
public class Talk : IAuditable
{
public int Id { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public List<TalkTag> TalkTags { get; set; }
public DateTime Presented { get; set; }
public DateTime ModifiedAt { get; set; }
public DateTime CreatedAt { get; set; }
}
}

TalkTag.cs​​

using System;
using System.Collections.Generic;
using System.Text;

namespace Conferency.Domain
{
public class TalkTag
{
public int TalkId { get; set; }
public Talk Talk { get; set; }
public int TagId { get; set; }
public Tag Tag { get; set; }
}
}

ConferencyContext.cs(删除无关代码)

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using System;
using Conferency.Domain;

namespace Conferency.Data
{
public class ConferencyContext: DbContext
{
public DbSet<Talk> Talks { get; set; }
public DbSet<Tag> Tags { get; set; }
public DbSet<TalkTag> TagTalks { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<TalkTag>()
.HasKey(s => new { s.TalkId, s.TagId });

modelBuilder.Entity<TalkTag>()
.HasOne(pt => pt.Talk)
.WithMany(p => p.TalkTags)
.HasForeignKey(pt => pt.TalkId);

modelBuilder.Entity<TalkTag>()
.HasOne(pt => pt.Tag)
.WithMany(t => t.TalkTags)
.HasForeignKey(pt => pt.TagId);

base.OnModelCreating(modelBuilder);
}
}
}

TalkViewModel.cs

using System;
using System.Collections.Generic;

namespace Conferency.Application.Models
{
public class TalkViewModel
{
public string Name { get; set; }
public string Url { get; set; }
public List<String> Tags { get; set; }
}
}

问题是我不知道如何创建演讲及其标签(如果存在则附加,如果不存在则创建)。我不确定以什么顺序来实现这一点。我是否必须查询每个标签以检查它们是否存在,或者是否有我可以使用的 findOrCreate 方法?如果尚未创建 Talk,如何创建 TalkTag 记录?有没有一种我不理解的优雅方法来完成此任务?

TalkRepository.cs

using System.Collections.Generic;
using Conferency.Domain;
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Threading.Tasks;

namespace Conferency.Data
{
public class TalkRepository : ITalkRepository
{
private ConferencyContext _context;

public TalkRepository(ConferencyContext context)
{
_context = context;
}

public void Add(Talk entity)
{
_context.Add(entity);
}

public void AddWithTags(Talk entity, List<String> tags)
{
// Create Talk
// Query for each tag
// Create if they don't exist
// Attach to talk
// ??
}

public IEnumerable<Talk> GetAllTalks()
{
return _context.Talks
.Include(c => c.TalkTags)
.OrderBy(c => c.Presented)
.ToList();
}

public Talk GetTalk(int id)
{
return _context.Talks
.Include(c => c.TalkTags)
.Where(c => c.Id == id)
.FirstOrDefault();
}

public async Task<bool> SaveAllAsync()
{
return (await _context.SaveChangesAsync()) > 0;
}
}
}

我是 C# 新手,我正在尝试学习最佳实践并熟悉 EF 和 ASP.NET Core,因此希望有人可以帮助指导我走上正确的道路。如果您想查看完整的解决方案,请看 https://github.com/bliitzkrieg/Conferency

我尝试自己解决这个问题,但出现 NullPointerException,这是我尝试的解决方案:

TalksController.cs

  [HttpPost()]
public async Task<IActionResult> Post([FromBody]TalkViewModel model)
{
try
{
_logger.LogInformation("Creating a new Talk");

List<Tag> tags = _tagRepo.FindOrCreateTags(model.Tags);

Talk talk = new Talk { Name = model.Name, Url = model.Url };

List<TalkTag> talkTags = new List<TalkTag>();
tags.ForEach(tag =>
{
var talkTag = new TalkTag { TagId = tag.Id, Talk = talk };
talkTags.Add(talkTag);
});

talk.TalkTags.AddRange(talkTags); // Exception being thrown here
_repo.Add(talk);

if (await _repo.SaveAllAsync())
{
string newUri = Url.Link("TalkGet", new { id = talk.Id });
return Created(newUri, talk);
}
else
{
_logger.LogWarning("Could not save Talk");
}
}
catch (Exception ex)
{
_logger.LogError($"Threw exception while saving Talk: {ex}");
}

return BadRequest();
}
}

TagRepository.cs

using System;
using System.Collections.Generic;
using Conferency.Domain;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using System.Linq;

namespace Conferency.Data
{
public class TagRepository: ITagRepository
{
private ConferencyContext _context;

public TagRepository(ConferencyContext context)
{
_context = context;
}

public void Add(Tag entity)
{
_context.Add(entity);
}

public List<Tag> FindOrCreateTags(List<string> tags)
{
List<Tag> _tags = new List<Tag>();
tags.ForEach(t =>
{
try
{
var tag = _context.Tags
.Where(c => c.Name == t)
.FirstOrDefault();

if (tag != null)
{
_tags.Add(tag);
}
else
{
Tag created = new Tag { Name = t };
this.Add(created);
_tags.Add(created);
}
}
catch (Exception ex)
{

}

});

return _tags;
}

public async Task<bool> SaveAllAsync()
{
return (await _context.SaveChangesAsync()) > 0;
}
}
}

最佳答案

在您的TalkViewModel上添加List<TagViewModel>具有以下属性的属性:

public int TagId { get; set; }
public string TagName { get; set; }
public bool Selected { get; set; }

当您将 TalkViewModel 传递到您的存储库时,过滤掉选定的 TagViewModel并为每一个添加 TalkTag与适当的TagId给您TalkTags您的属性(property) Talk 。 EF 应注意添加正确的 TalkId_context.SaveChanges() .

如果Tag不存在,创建一个TalkTag有了新的Tag和新的Talk作为其属性,然后将其添加到您的 _context 。 EF 应该负责剩下的事情。

关于asp.net - 添加标签来讨论 Entity Framework 中的多对多关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44427501/

25 4 0