尝试保存实体时遇到客户端错误。 2个表同时具有一对多和一对一的关系,这导致以下错误:
无法确定“User”类型的导航属性“Group.LockedByUser”所代表的关系。手动配置关系,或使用'[NotMapped]'属性或在'OnModelCreating
中使用'EntityTypeBuilder.Ignore'忽略此属性
这些是我目前的背景:
用户实体
public class User
{
[Key]
public int UserId { get; set; }
public string Username { get; set; }
public int GroupId { get; set; }
public Group GroupThisUserBelongsTo { get; set; }
public ICollection<Group> GroupsLockedByThisUser { get; set; }
public ICollection<Config> Configs { get; set; }
}
群组实体
public class Group
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int GroupId { get; set; }
public string GroupName { get; set; }
public int? LockedByUserId { get; set; }
public User LockedByUser { get; set; }
public ICollection<User> Users { get; set; }
}
DbContext1提取
modelBuilder.Entity<Group>(entity =>
{
entity.HasOne(d => d.LockedByUser)
.WithMany(p => p.GroupsLockedByThisUser)
.HasForeignKey(d => d.LockedByUserId);
}
modelBuilder.Entity<User>(entity =>
{
entity.HasOne(d => d.GroupThisUserBelongsTo)
.WithMany(p => p.Users)
.HasForeignKey(d => d.GroupId)
.OnDelete(DeleteBehavior.ClientSetNull);
});
配置实体
public class Config
{
[Key]
public int ConfigId { get; set; }
public int UserId { get; set; }
public string Config { get; set; }
public User User { get; set; }
}
DbContext2摘录
modelBuilder.Entity<Config>(entity =>
{
entity.HasOne(d => d.User)
.WithMany(p => p.Configs)
.HasForeignKey(d => d.UserId);
});
产生错误的代码如下:
var config = new Config {
UserId = 123456,
Config = "test"
};
_dbContext2.Config.Add(config);
_dbContext2.SaveChanges();
我真的不明白为什么在尝试保存该实体时出现客户端错误。该错误甚至不是我试图保存的上下文。
我的外键设置正确吗?
Group
有很多User
- User
只有一个Group
(FK GroupId
)User
锁定零个或多个Group
(FK LockedByUserId
)Config
有一个User
(FK UserId
)答案 0 :(得分:0)
试图重现错误。没有repro:
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
//using Microsoft.Samples.EFLogging;
using System.Data.SqlClient;
using System.Xml.Linq;
using System.Threading.Tasks;
namespace EFCore2Test
{
public class User
{
[Key]
[DatabaseGenerated( DatabaseGeneratedOption.None)]
public int UserId { get; set; }
public string Username { get; set; }
public int GroupId { get; set; }
public Group GroupThisUserBelongsTo { get; set; }
public ICollection<Group> GroupsLockedByThisUser { get; set; }
public ICollection<Config> Configs { get; set; }
}
public class Group
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int GroupId { get; set; }
public string GroupName { get; set; }
public int? LockedByUserId { get; set; }
public User LockedByUser { get; set; }
public ICollection<User> Users { get; set; }
}
public class Config
{
[Key]
public int ConfigId { get; set; }
public int UserId { get; set; }
public string ConfigName { get; set; }
public User User { get; set; }
}
public class Db : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Group> Groups { get; set; }
public DbSet<Config> Configs { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Group>()
.HasOne(d => d.LockedByUser)
.WithMany(p => p.GroupsLockedByThisUser)
.HasForeignKey(d => d.LockedByUserId);
modelBuilder.Entity<User>()
.HasOne(d => d.GroupThisUserBelongsTo)
.WithMany(p => p.Users)
.HasForeignKey(d => d.GroupId)
.OnDelete(DeleteBehavior.ClientSetNull);
modelBuilder.Entity<Config>()
.HasOne(d => d.User)
.WithMany(p => p.Configs)
.HasForeignKey(d => d.UserId);
base.OnModelCreating(modelBuilder);
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Server=(local);Database=EFCoreTest;Trusted_Connection=True;MultipleActiveResultSets=true");
base.OnConfiguring(optionsBuilder);
}
}
class Program
{
static void Main(string[] args)
{
using (var db = new Db())
{
db.Database.EnsureDeleted();
db.Database.EnsureCreated();
//db.ConfigureLogging(s => Console.WriteLine(s));
var g = new Group()
{
GroupName = "G"
};
var u = new User()
{
UserId = 123456,
GroupThisUserBelongsTo = g
};
db.Users.Add(u);
db.SaveChanges();
g.LockedByUser = u;
db.SaveChanges();
}
using (var db = new Db())
{
var config = new Config
{
UserId = 123456,
ConfigName = "test"
};
db.Configs.Add(config);
db.SaveChanges();
}
Console.WriteLine("Hit any key to exit");
Console.ReadKey();
}
}
}
答案 1 :(得分:0)
正如in this answer所述,我需要复制共享关系。
使用DbContext2
时,User
和Group
之间的关系未定义。
我可以通过使用单个上下文或让上下文继承定义所有共享关系的主上下文来解决我的问题。