简体   繁体   English

Map 表行到 DDD 值 object 带 EF 内核

[英]Map table row to DDD value object woith EF core

scenario设想

I have two aggregates in my microservice Domain model: User and UserNotification.我的微服务域 model 中有两个聚合:用户和用户通知。

public class User : Aggreagete
{
    public int Id { get; private set; }
}

public class UserNotification : Aggreagete
{
    public int Id { get; private set; }

    public int UserId { get; private set; }

    public bool EnableSms { get; private set; }

    public bool EnableEmail { get; private set; }

    public NotificationKind NotificationKind { get; private  set; }

    public UserModel User { get;private set }
}

UserValueObject needs to be mapped from the same table as User Aggregate. UserValueObject 需要从与 User Aggregate 相同的表中映射。 I use UserValueObject because from Notification bounded Context it needs to be immutable.我使用 UserValueObject 因为从通知有界上下文它需要是不可变的。

I have following EF mappings:我有以下 EF 映射:

    public void Configure(EntityTypeBuilder<User> builder)
    {
        builder.ToTable("Users", SCHEME);

        builder.HasKey(o => o.Id);
        builder.Property(o => o.Id);

        builder.HasMany<UserNotification>()
            .WithOne()
            .HasForeignKey(entry => entry.UserId)
            .OnDelete(DeleteBehavior.Cascade);
    }

    public void Configure(EntityTypeBuilder<UserNotification> builder)
    {
        builder.ToTable("UserNotifications", SCHEME);

        builder.HasKey(o => o.Id);
        builder.Property(o => o.Id);

        builder.Property(e => e.UserId).IsRequired();
        builder.Property(e => e.EnableSms).IsRequired();
        builder.Property(e => e.EnableEmail).IsRequired();
        builder.Property(e => e.NotificationKind).IsRequired()
            .HasConversion(
                v => v.ToString(),
                strValue => Enum.Parse<NotificationKind>(strValue)
            );
        builder.OwnsOne(e => e.User).ToTable("Users");
    }

problem问题

I receive error during "Add Migration"我在“添加迁移”期间收到错误

Cannot use table 'dbo.Users' for entity type 'User' since it is being used for entity type 'UserModel' and there is no relationship between their primary keys.

UserModel is:用户模型是:

public class UserModel : ValueObject
{
    public int Id { get; private set; }
    public string Email { get; private set; }
    public string Phone { get; private set; }
    public string Name { get; private set; }
}

question问题

I would like to map UserModel.Id from database table "Users", but Email, Phone and Name should be injected in repository with using HTTP request to Identity Service.我想从数据库表“用户”中获取 map UserModel.Id,但是 Email,电话和姓名应该使用 HTTP 请求注入到存储库中。 Is is possible to do such operation with EF core?是否可以使用 EF 核心进行此类操作? I see that it is not possible to achieve this with owned entity, because Users table is used also to mapped other aggreagate.我看到使用拥有的实体无法实现这一点,因为用户表也用于映射其他聚合。

You are getting the correct exception due to the name conflict.由于名称冲突,您得到了正确的异常。

For the User entity you ask EF to use the Users table:对于User实体,您要求 EF 使用Users表:

builder.ToTable("Users", SCHEME);

but you also ask it to use the same table to store value objects of the UserNotification entity:但您也要求它使用同一张表来存储UserNotification实体的值对象:

builder.OwnsOne(e => e.User).ToTable("Users");

If your plan is to "reuse" the Users aggregate persistence to magically map the value project to it than I can definitely tell that it's not a good idea.如果您的计划是“重用” Users聚合持久性以神奇地 map 对它的价值项目,我可以肯定地说这不是一个好主意。

Value objects are typed pieces of state.值对象是 state 的类型片段。 They belong to entities and managed by entities.它们属于实体,由实体管理。 You have to update the content of the VO when needed.您必须在需要时更新 VO 的内容。

You also don't need to keep the user information in the aggregate, unless you use it in any of the methods of your notification aggregate.您也不需要将用户信息保存在聚合中,除非您在通知聚合的任何方法中使用它。 If you need to be able to query and join - just do that in the query.如果您需要能够查询和加入 - 只需在查询中执行此操作。 Don't use EF for queries and write a plain SQL with inner join to get the information you need.不要使用 EF 进行查询,而是使用内部连接编写一个普通的 SQL 来获取您需要的信息。 Look up CQRS, Jimmy Bogard advocated using EF for the write side and plain SQL queries for the read side some time ago, it makes total sense.查找 CQRS,Jimmy Bogard 前段时间提倡使用 EF 作为写入端,使用普通的 SQL 查询作为读取端,这完全有道理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM