Asp.net 为实体框架中的多对多关系添加标签
我正在创建一个API端点,该端点创建一个新的对话,其中包含应该与对话关联的标记。我在我的域中的标签和对话之间建立了多对多关系,请参见下面的关系 Tag.csAsp.net 为实体框架中的多对多关系添加标签,asp.net,entity-framework,asp.net-core,entity-framework-core,Asp.net,Entity Framework,Asp.net Core,Entity Framework Core,我正在创建一个API端点,该端点创建一个新的对话,其中包含应该与对话关联的标记。我在我的域中的标签和对话之间建立了多对多关系,请参见下面的关系 Tag.cs using System; using System.Collections.Generic; namespace Conferency.Domain { public class Tag : IAuditable { public int Id { get; set; } public s
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; }
}
}
ConferencyContext.cs(已删除不相关的代码)
使用Microsoft.EntityFrameworkCore;
使用Microsoft.EntityFrameworkCore.ChangeTracking;
使用制度;
使用授予域;
名称空间协商.Data
{
公共类ConferencyContext:DbContext
{
公共DbSet会话{get;set;}
公共DbSet标记{get;set;}
公共DbSet TagTalks{get;set;}
模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
modelBuilder.Entity()
.HasKey(s=>new{s.TalkId,s.TagId});
modelBuilder.Entity()
.HasOne(pt=>pt.Talk)
.WithMany(p=>p.TalkTags)
.HasForeignKey(pt=>pt.TalkId);
modelBuilder.Entity()
.HasOne(pt=>pt.Tag)
.WithMany(t=>t.TalkTags)
.HasForeignKey(pt=>pt.TagId);
基于模型创建(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; }
}
}
使用系统;
使用System.Collections.Generic;
命名空间conference.Application.Models
{
公共类TalkViewModel
{
公共字符串名称{get;set;}
公共字符串Url{get;set;}
公共列表标记{get;set;}
}
}
问题是我不知道如何创建一个对话及其标签(如果它们存在,请附加,如果不存在,请创建)。我不确定要以什么样的方式来实现这一点。我是否必须查询每个标记以检查它们是否存在,或者是否有可以使用的findOrCreate方法?如果尚未创建对话,如何创建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;
}
}
}
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;
}
}
}
使用System.Collections.Generic;
使用授予域;
使用Microsoft.EntityFrameworkCore;
使用制度;
使用System.Linq;
使用System.Threading.Tasks;
名称空间协商.Data
{
公共类TalkRepository:ITalkRepository
{
私人会议背景(context);;
公共演讲库(ConferencyContext)
{
_上下文=上下文;
}
公共无效添加(对话实体)
{
_添加(实体);
}
公共void AddWithTags(对话实体、列表标记)
{
//创造对话
//查询每个标记
//如果它们不存在,就创建它们
//附和谈话
// ??
}
公共IEnumerable GetAllTalks()
{
返回上下文
.包括(c=>c.TalkTags)
.OrderBy(c=>c.Presented)
.ToList();
}
公共谈话GetTalk(int-id)
{
返回上下文
.包括(c=>c.TalkTags)
.其中(c=>c.Id==Id)
.FirstOrDefault();
}
公共异步任务SaveAllAsync()
{
返回(wait_context.saveChangesSync())>0;
}
}
}
我是c#新手,我正在努力学习最佳实践,熟悉EF和ASP.NET Core,希望有人能帮助我走上正确的道路。如果您想看一看,完整的解决方案就在这里
我试着自己解决它,但我得到了一个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();
}
}
[HttpPost()]
公共异步任务帖子([FromBody]TalkViewModel)
{
尝试
{
_logger.LogInformation(“创建新对话”);
列表标签=_tagRepo.FindOrCreateTags(model.tags);
Talk Talk=new Talk{Name=model.Name,Url=model.Url};
List talkTags=新列表();
tags.ForEach(tag=>
{
var-talkTag=new-talkTag{TagId=tag.Id,Talk=Talk};
talkTags.添加(talkTag);
});
talk.TalkTags.AddRange(TalkTags);//此处引发异常
_回购加(谈);
如果(等待_repo.SaveAllAsync())
{
字符串newUri=Url.Link(“TalkGet”,new{id=talk.id});
创建的返回(newUri、talk);
}
其他的
{
_logger.LogWarning(“无法保存对话”);
}
}
捕获(例外情况除外)
{
_logger.LogError($“保存对话时引发异常:{ex}”);
}
返回请求();
}
}
TagRepository.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;
}
}
}
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;
}
}
}
使用系统;
使用System.Collections.Generic;
使用授予域;
使用System.Threading.Tasks;
使用Microsoft.EntityFrameworkCore;
使用System.Linq;
名称空间协商.Data
{
公共类标记存储库:ITagRepository
{
私人会议背景(context);;
公共标记库(上下文上下文)
{
_上下文=上下文;
}
公共无效添加(标记实体)
{
_添加(实体);
}
公共列表FindOrCreateTags(列表标记)
{
列表_标记=新列表();
tags.ForEach(t=>
{
尝试
{
var tag=\u context.Tags
.Where(c=>c.Name==t)
.FirstOrDefault();
如果(标记!=null)
{
_标签。添加(标签);
}
其他的
{
创建的标记=新标记{Name=t};
添加(已创建);
_标签。添加(创建);
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;
}
}
}
public int TagId { get; set; }
public string TagName { get; set; }
public bool Selected { get; set; }
Talk talk = new Talk { Name = model.Name, Url = model.Url, TalkTags = new List<TalkTag>() };