Entity Framework Core:如何映射多个相同类型的对象

bin*_*bin 3 c# entity-framework-core .net-core

我有两个类,一个用于User,一个用于Warn上述用户可以接收的类,我想映射它们,但我在这样做时遇到了问题。

using System;
using System.Collections.Generic;
using System.Linq;

namespace web
{
    public class User
    {
        public User()
        {
        }

        public ICollection<MuteWarn> Mutes { get; set; }
        public ICollection<Warn> Warns { get; set; }
        public ICollection<Ban> Bans { get; set; }
        public ICollection<Kick> Kicks { get; set; }
        public int Id { get; set; }
        public ulong DiscordId { get; set; }
        public bool AntiBan { get; set; }
        public ICollection<string> Permissions { get; set; }
        public Level Level { get; set; }
        public Mute CurrentMute { get; set; }

        public string Name { get; set; }
        public int Discrim { get; set; }
        public string AvatarUrl { get; set; }
        public Guild Guild { get; set; }

        public bool HasPermission(string perm)
        {
            var res = Permissions.Where(x => x == perm);
            if(res != null) return true;
            return false;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是User课程,这是Warn课程:

using System;

namespace web
{
    public class Warn
    {
        public Warn()
        {
              Moderator = DataHelper.GetDefaultModerator();
        }

        public int Id { get; set; }
        public string Reason { get; set; }
        public DateTime Timestamp { get; set; }
        public User Moderator { get; set; }

        public User User { get; set; }
        public Guild Guild { get; set; }
    }
}
Run Code Online (Sandbox Code Playgroud)

如您所见,此类User中有两个类型的对象,我想从 User 类访问它们,如下所示:

foreach(var w in User.Warns)
{
     Console.WriteLine(w.Reason); 
     Console.WriteLine(w.Moderator.Name); 
}
Run Code Online (Sandbox Code Playgroud)

等等。

版主和用户是两个不同的用户(即使他们可以是同一个人)。

版主是发出警告的人,用户是收到警告的用户。

每个用户可以有无限数量的警告。

出于某种原因,这不会建立,因为它找不到版主和用户之间的关系。

请帮忙,谢谢。

Smi*_*mit 5

EF Core 具有根据域类结构确定元数据部分的约定。通常导航属性表示声明类型和目标类型之间存在关系。如果在声明类型的目标类型中有导航,则它们被视为定义关系的导航对。尽管在查找构成关系的导航对方面存在限制。如果存在歧义,则 EF Core 将不会创建关系。在您的案例中,User类有一个Warns具有目标类型的导航,Warn但类Warn有 2 个类型的导航User- Moderator&User. 现在 EF 无法确定哪些导航是单一关系的一部分。所以这需要用户配置来定义关系从而正确构建模型。

假设User.Warns&Warn.User是 1 关系的一部分,因为警告包含用户收到的所有警告,因此Warn.User应该指向User. 并且Warn.Moderator是没有反向导航的单独关系。有 2 种方法可以配置它。

数据注释

您可以InverseProperty在导航上使用属性来告诉 EF Core 此导航的反向导航是什么。在您的情况下,这两种方法都可以解决问题。

[InverseProperty("User")]
public ICollection<Warn> Warns { get; set; }
Run Code Online (Sandbox Code Playgroud)

或者

[InverseProperty("Warns")]
public User User { get; set; }
Run Code Online (Sandbox Code Playgroud)

这将解决歧义并帮助 EF 找出对,以便约定将创建关系。

流利的API

您可以使用 fluent api 显式配置关系。您需要将此代码放在您的DbContext.OnModelCreating方法中。

modelBuilder.Entity<User>().HasMany(e => e.Warns).WithOne(e => e.User);
Run Code Online (Sandbox Code Playgroud)

或者

modelBuilder.Entity<Warn>().HasOne(e => e.Moderator).WithMany();
Run Code Online (Sandbox Code Playgroud)

再次定义以上任何一项都可以消除歧义,并且模型构建正确。

有关如何配置关系的更多详细信息,您可以在文档中阅读