如何从具有多对多关系的C#Web API Visual Studio 2017 RTM提供(G
我很久以来一直坚持这个问题.
我的环境: > Visual Studio 2017 RTM(使用此IDE的默认.net核心版本) 我安装的包: Microsoft.EntityFrameworkCore Pomelo.EntityFrameworkCore.MySql Microsoft.EntityFrameworkCore.Tools 我首先使用代码创建了3个表. >员工:有员工名单 Employee和Application具有M:M关系,因此我在它们之间创建了连接表. 员工模型: using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.ComponentModel.DataAnnotations; namespace Test.Models { public class Employee { public int EmployeeId { get; set; } [Required] public string LName { get; set; } [Required] public string FName { get; set; } public string Title { get; set; } //Navigation Property public ICollection<EmployeeApplications> EmployeeApplications { get; set; } } } 应用模型: using System.Linq; using System.Threading.Tasks; using System.ComponentModel.DataAnnotations; namespace Teset.Models { public class Application { public int ApplicationId { get; set; } [Required] public string Name { get; set; } public string Description { get; set; } //Navigation Property public ICollection<EmployeeApplications> EmployeeApplications { get; set; } } } 员工应用模型: using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace Test.Models { public class EmployeeApplications { public int EmployeeId { get; set; } public int ApplicationId { get; set; } public Employee Employee { get; set; } public Application Application { get; set; } } } 员工控制员: [Produces("application/json")] [Route("api/Employees")] public class EmployeesController : Controller { private readonly TestContext _context; public EmployeesController(TestContext context) { _context = context; } // GET: api/Employees [HttpGet] public IEnumerable<Employee> GetEmployees() { return _context.Employees; } 语境: using Test.Models; using Microsoft.EntityFrameworkCore; namespace Test.Data { public class TestContext : DbContext { public TestContext(DbContextOptions<TestContext> options) : base(options) { } public DbSet<Employee> Employees { get; set; } public DbSet<Application> Applications { get; set; } public DbSet<EmployeeApplications> EmployeeApplications { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<EmployeeApplications>() .HasKey(c => new { c.EmployeeId,c.ApplicationId }); } } } 我尝试过使用.Include().当我跑去api / Employees时,我得到Postman的“无法得到任何回应”. return _context.Employees.Include(e => e.EmployeeApplications); 我已经尝试了很多变化,但仍然没有运气.包含.Include()的任何变体都会失败. 电流输出样本: [{ "employeeId": 1,"lName": "Doe","fName": "John","title": "Senior Software Engineer","employeeApplications": null },{ "employeeId": 2,"lName": "Smith","fName": "Jack","title": "Project Manager","employeeApplications": null }] 我尝试使用DTO并取得了一些成功.我设法用employeeApplications中的内容替换上面的null,但是后来对Employee和Applications有了null引用. 我理想的输出: [{ "employeeId": 1,"employeeApplications": [{ "applicationId": 1,"name": "Application 1","description": "Description 1",},{ "applicationId": 2,"name": "Application 2","description": "Description 2",}] },"employeeApplications": [{ "applicationId": 2,{ "applicationId": 3,"name": "Application 3","description": "Description 3",}] }] 基本上我想提供一份“员工”列表和他们所使用的应用程序.稍后我还要提供一份应用程序列表和处理它们的员工. 编辑:上面添加了上下文文件 编辑2:我遵循Bchir Med Amine的解决方案(目前没有工作),但后来我添加到Startup.cs的ConfigureServices方法: services.AddMvc() .AddJsonOptions( options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore ); 这让我获得了有关我的JSON的更多信息,但仍未完整. JSON现在看起来像这样: [{ "employeeId": 1,"employeeApplications": [{ "employeeId": 1,"applicationId": 1,"application": null },{ "employeeId": 1,"applicationId": 2,"application": null }] },"employeeApplications": [{ "employeeId": 2,{ "employeeId": 2,"applicationId": 3,"application": null }] }] 应用程序现在为null.我不得不使用.Include()来生成它,但是在包含应用程序之后使用.ThenInclude()不起作用.理想的情况是打印出所有员工的清单,每个员工都应该有一份申请清单. 编辑3:我错了.ThenInclude()没有工作,是Intelisense让我失望.如果我使用.ThenInclud()我得到这个JSON: [{ "employeeId": 1,"application": { "applicationId": 1,"employeeApplications": [] } },"application": { "applicationId": 2,"employeeApplications": [] } }] },"employeeApplications": [{ "employeeId": 1,"employee": { "employeeId": 1,"employeeApplications": [{ "employeeId": 1,"application": { "applicationId": 1,"employeeApplications": [] } }] } }] } },"application": { "applicationId": 3,"employeeApplications": [] } }] }] 第一个员工对象是Ok(仍然不理想,但它可以工作),但第二个员工不是.第二个打印出员工的应用程序,然后打印出这些应用程序的员工. 编辑4:以下是我返回JSON的方式: return _context.Employees; //Returns just employees and '[]' for employeeApplications return _context.Employees.Include(e => e.EmployeeApplications); //returns employees and their employeeApplications,but the applications of employeeApplications is empty return _context.Employees.Include(e => e.EmployeeApplications).ThenInclude(ea => ea.Application); //returns everything,but continues due to circular reference 解决方法
也许你必须将Virtual添加到类中
public class Application { #region Public Constructors [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage","CA2214:DoNotCallOverridableMethodsInConstructors")] public Application() { EmployeeApplications = new HashSet<EmployeeApplications>(); } #endregion Public Constructors #region Public Properties public int ApplicationId { get; set; } public string Description { get; set; } //Navigation Property public virtual ICollection<EmployeeApplications> EmployeeApplications { get; set; } [Required] public string Name { get; set; } #endregion Public Properties } public class Employee { #region Public Constructors [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage","CA2214:DoNotCallOverridableMethodsInConstructors")] public Employee() { EmployeeApplications = new HashSet<EmployeeApplications>(); } #endregion Public Constructors #region Public Properties //Navigation Property public virtual ICollection<EmployeeApplications> EmployeeApplications { get; set; } public int EmployeeId { get; set; } [Required] public string FName { get; set; } [Required] public string LName { get; set; } public string Title { get; set; } #endregion Public Properties } public class EmployeeApplications { #region Public Properties public virtual Application Application { get; set; } public int ApplicationId { get; set; } public virtual Employee Employee { get; set; } public int EmployeeId { get; set; } #endregion Public Properties } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |