【问题标题】:Criss-cross inheritance realization and EF Core 3.0交叉继承实现与EF Core 3.0
【发布时间】:2019-11-07 15:01:23
【问题描述】:

我有一个关于“交叉”继承的问题。

我们来上课吧。

public class User
{
    public string UserName { get; set; }
    public ICollection<Notification> Notifications { get; set; }
}

public class Notification
{
    public string Message { get; set;}
    public int NotificationType { get; set; }
}

这些是基类。

现在我想以此创建 EF Core 模型。

public class EFUser : User
{
    public Guid Id { get; set; }
}

public class EFNotification : Notification
{
    public Guid Id { get; set; }

    public Guid EFUserId { get; set; }
    public EFUser EFUser { get; set; }
}

但正如我们所见,EFUser 有一个ICollection&lt;Notification&gt; Notifications,而不是ICollection&lt;EFNotification&gt; Notifications,因此,这个模型可以迁移到数据库。 据我了解,virtual 关键字的使用不会给我一个解决方案,因为public virtual ICollection&lt;Notification&gt; Notifications 不会改变底层类型。

有没有办法实现这样的构造?

本示例的主要思想是实现“类的基本结构”,可以通过包装在 EF Core 对象模型、DTO 等中使用。

【问题讨论】:

  • 即使可以做到,它也会在您的数据模型和域模型(我猜是的)之间创建紧密耦合。完全不推荐。将它们分开并使用映射。

标签: c# .net entity-framework inheritance


【解决方案1】:

我建议改为创建一个完全独立的实体类。然后映射到/映射到您的模型类。

public class EFUser
{
    public Guid Id { get; set; }
    public string UserName { get; set; }
    public ICollection<EFNotification> Notifications { get; set; }
}

public class Mapper // or use AutoMapper
{
    public EFUser Map(User user)
    {
        return new EFUser
        {
            UserName = user.UserName,
            Notifications = Map(user.Notifications)
        }
    }
}

【讨论】:

  • 我知道这个解决方案,我想扩展/改进它,因为我需要为我的项目中的类之间的每个桥梁编写映射(例如,对于请求和响应类等) .
  • 此外,对于深度继承结构,它应该使用巨大的开销。
【解决方案2】:

这看起来是一个很好的泛型用例

public class User<TNotification> where TNotification : Notification {
    public string UserName { get; set; }
    public ICollection<TNotification> Notifications { get; set; }
}

默认的User 类基本上是User&lt;Notification&gt;

例如

public class User : User<Notification> {
    //Which works out to having
    //public ICollection<Notification> Notifications { get; set; }
}

现在拥有通用基类允许

public class EFUser : User<EFNotification> {
    public Guid Id { get; set; }
}

这意味着EFUser 现在将具有ICollection&lt;EFNotification&gt; Notifications 属性。

【讨论】:

  • 非常感谢!这就是我正在寻找的解决方案!使用紧密耦合是明智的决定,因为我可以将域模型和数据传输模型连接到同一个基础,并通过 fluent api 或 Map.Ignore 实现模型调整。而且,当然,域模型和数据传输模型通过 AutoMapper 连接在一起。因此,基础类的每次修改都会自动更改所有派生类以及域模型和数据传输模型之间的映射。希望,我清楚地解释了我的想法。
猜你喜欢
  • 2021-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-18
  • 2022-11-17
  • 1970-01-01
  • 1970-01-01
  • 2023-02-04
相关资源
最近更新 更多