[英]EF Core 3.1 Fluent API
我有两个实体:
审计 class :
public class Audit
{
public string AuditId{get;set;}
public int EmployeeId{get;set;}
public virtual ModEmployee{get;set;}
}
员工 class :
public class Employee
{
public int EmployeeId{get;set}
}
在加载Set<Audit>
时,我希望填充 Audit class 的 Employee 属性。 这显然是一对多关系的情况,其中一个审计将有一个员工,但一个员工可以在多个审计中。
我的 Fluent API 如下所示:
protected override OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Audit>()
.HasOne(a=>a.ModEmployee)
.WithMany()
.HasForeignKey("EmployeeId");//a=>a.EmployeeId wont work.
}
我一直在寻找解决方案一段时间,并从这个答案中获取了一些输入,但它是一对一的。 然后这个资源显示了一种方法,但这需要我在员工 class 中收集审计。
我无法更改现有模型或添加注释,因为它们已被其他实体框架版本(非核心)使用。
目前我收到以下错误:
System.InvalidOperationException:'无法确定'Employee'类型的导航属性'Employee.ModEmployee'表示的关系。 手动配置关系,或使用“[NotMapped]”属性或使用“OnModelCreating”中的“EntityTypeBuilder.Ignore”忽略此属性。
如果我在 Audit 的构建器上添加忽略方法,错误就会消失,如下所示: .Ignore(a=>a.ModEmployee)
但我不会在 Audit 中获得实体 object。 任何帮助将不胜感激。 我在 EFCore 3.1.10 上。 谢谢阅读。 任何帮助将不胜感激。
尝试在Audit
class 中将类型从int
更改为Employee
。 应该可以正常工作,因为这是在流畅的 API 中关联外键的正确方法。
PS:FK 属性字符串应与Employee
中的完全相同,这已经发生了。
我最近有同样的问题。 这对我有用:
方法 1:参考 Audit 集合定义您的 Employee class:
public class Employee
{
public int EmployeeId { get; set }
public virtual ICollection<Audit> Audits { get; set; }
}
然后在您的 model 构建器中以这种方式定义关系:
builder.Entity<Audit>().HasOne(e => e.ModEmployee).WithMany(ae => ae.Audits).HasForeignKey(k => k.EmployeeId);
您总是需要在每个 class 中定义集合。
编辑!!
方法二:
public class Audit
{
public string AuditId{get;set;}
public Employee Employee { get; set; }
}
我知道这需要你编辑你的 class 但相信我这会让事情变得更容易。
如果您无法修改 model 类。
您可以简单地在您的上下文中添加一个检索审计的方法。
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace EFCoreFluentApi1.Context
{
public class MyContext : DbContext
{
public DbSet<Audit> Audit { get; set; }
public DbSet<Employee> Employee { get; set; }
public MyContext(DbContextOptions options) : base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<Employee>().HasKey(e => e.EmployeeId);
builder.Entity<Employee>().Property(e => e.EmployeeId);
builder.Entity<Audit>().HasKey(e => e.AuditId);
builder.Entity<Audit>().Property(e => e.AuditId);
builder.Entity<Audit>().HasOne(e => e.ModEmployee).WithMany().HasForeignKey(e => e.EmployeeId);
builder.Entity<Employee>().HasData(new Employee[]
{
new Employee{ EmployeeId = 1 },
new Employee{ EmployeeId = 2 },
new Employee{ EmployeeId = 3 },
new Employee{ EmployeeId = 4 }
});
builder.Entity<Audit>().HasData(
new Audit[]
{
new Audit
{
AuditId = "Audit1",
EmployeeId = 1
},
new Audit
{
AuditId = "Audit2",
EmployeeId = 1
},
new Audit
{
AuditId = "Audit3",
EmployeeId = 1
},
new Audit
{
AuditId = "Audit4",
EmployeeId = 2
},
new Audit
{
AuditId = "Audit5",
EmployeeId = 3
},
new Audit
{
AuditId = "Audit6",
EmployeeId = 3
},
new Audit
{
AuditId = "Audit7",
EmployeeId = 4
},
new Audit
{
AuditId = "Audit8",
EmployeeId = 4
},
new Audit
{
AuditId = "Audit9",
EmployeeId = 4
},
new Audit
{
AuditId = "Audit10",
EmployeeId = 4
}
});
}
public ICollection<Audit> GetAudits(int employeeId)
{
return Audit.Where(e => e.EmployeeId == employeeId).ToList();
}
}
}
如果需要填充 ModEmployee,可以使用 Include 方法。
using EFCoreFluentApi1.Context;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using System;
using System.IO;
using System.Linq;
using System.Text.Json;
namespace EFCoreFluentApi1
{
class Program
{
static void Main(string[] args)
{
IConfiguration configuration = new ConfigurationBuilder().
SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", false, true)
.Build();
DbContextOptions options = new DbContextOptionsBuilder<MyContext>()
.UseSqlServer(configuration.GetConnectionString("MyConnectionString"))
.EnableSensitiveDataLogging(true).Options;
using (var context = new MyContext(options))
{
var result = context.Audit.Include(e => e.ModEmployee).ToList(); //ModEmployee is populated
//var result = context.Audit.ToList(); //ModEmployee = null
foreach (var value in result)
{
Console.WriteLine($"█ Audit: {value.AuditId}");
Console.WriteLine(JsonSerializer.Serialize(value));
Console.WriteLine();
}
Console.ReadLine();
}
}
}
}
检查我在https://github.com/JomaStackOverflowAnswers/EFCoreFluentApi1中的示例这个项目是<TargetFramework>netcoreapp3.1</TargetFramework>
检查 IsRequired 显式https://docs.microsoft.com/en-us/ef/core/modeling/entity-properties?tabs=fluent-api%2Cwithout-nrt#explicit-configuration
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.