c# - Entity Framework Core 中的强类型 ID

标签 c# entity-framework .net-core entity-framework-core domain-driven-design

我正在尝试使用强类型 Id类,现在在内部保持“长”。下面实现。
我在我的实体中使用它的问题是 Entity Framework 给了我一条消息,表明属性 Id 已经映射到它上面。看我的 IEntityTypeConfiguration以下。

注:我的目标不是严格执行 DDD。所以请在评论或回答时记住这一点。键入 Id 后面的整个 ID适用于进入项目的开发人员,他们被强类型化为在所有实体中使用 Id,当然翻译为 long (或 BIGINT )-但对其他人来说很清楚。

在类和配置下面,这是行不通的。
可以在 https://github.com/KodeFoxx/Kf.CleanArchitectureTemplate.NetCore31 找到该存储库。 ,

  • Id类(class)(现已注释掉):https://github.com/KodeFoxx/Kf.CleanArchitectureTemplate.NetCore31/blob/master/Source/Common/Kf.CANetCore31/DomainDrivenDesign/Id.cs
  • EntityValueObject类(对于 Entity,属性 Id 的类型是 Id .cs(上图):https://github.com/KodeFoxx/Kf.CleanArchitectureTemplate.NetCore31/tree/master/Source/Common/Kf.CANetCore31/DomainDrivenDesign
  • 配置地址:https://github.com/KodeFoxx/Kf.CleanArchitectureTemplate.NetCore31/tree/master/Source/Infrastructure/Persistence/Kf.CANetCore31.Infrastructure.Persistence.Ef/EntityTypeConfigurations

  • Id类实现 (现在标记为过时,因为我放弃了这个想法,直到找到解决方案)
    namespace Kf.CANetCore31.DomainDrivenDesign
    {
        [DebuggerDisplay("{DebuggerDisplayString,nq}")]
        [Obsolete]
        public sealed class Id : ValueObject
        {
            public static implicit operator Id(long value)
                => new Id(value);
            public static implicit operator long(Id value)
                => value.Value;
            public static implicit operator Id(ulong value)
                => new Id((long)value);
            public static implicit operator ulong(Id value)
                => (ulong)value.Value;
            public static implicit operator Id(int value)
                => new Id(value);
    
    
            public static Id Empty
                => new Id();
    
            public static Id Create(long value)
                => new Id(value);
    
            private Id(long id)
                => Value = id;
            private Id()
                : this(0)
            { }
    
            public long Value { get; }
    
            public override string DebuggerDisplayString
                => this.CreateDebugString(x => x.Value);
    
            public override string ToString()
                => DebuggerDisplayString;
    
            protected override IEnumerable<object> EquatableValues
                => new object[] { Value };
        }
    }
    

    EntityTypeConfiguration当 Id 未标记为实体 Person 已过时时,我正在使用不幸的是,当类型为 Id 时,EfCore 不想映射它......当类型为 long 时没有问题......其他拥有的类型,如您所见(使用 Name )工作正常。
    public sealed class PersonEntityTypeConfiguration
            : IEntityTypeConfiguration<Person>
        {
            public void Configure(EntityTypeBuilder<Person> builder)
            {
                // this would be wrapped in either a base class or an extenion method on
                // EntityTypeBuilder<TEntity> where TEntity : Entity
                // to not repeated the code over each EntityTypeConfiguration
                // but expanded here for clarity
                builder
                    .HasKey(e => e.Id);
                builder
                    .OwnsOne(
                    e => e.Id,
                    id => {
                       id.Property(e => e.Id)
                         .HasColumnName("firstName")
                         .UseIdentityColumn(1, 1)
                         .HasColumnType(SqlServerColumnTypes.Int64_BIGINT);
                    }
    
                builder.OwnsOne(
                    e => e.Name,
                    name =>
                    {
                        name.Property(p => p.FirstName)
                            .HasColumnName("firstName")
                            .HasMaxLength(150);
                        name.Property(p => p.LastName)
                            .HasColumnName("lastName")
                            .HasMaxLength(150);
                    }
                );
    
                builder.Ignore(e => e.Number);
            }
        }
    

    Entity基类(当我还在使用 Id 时,所以当它没有被标记为过时)
    namespace Kf.CANetCore31.DomainDrivenDesign
    {
        /// <summary>
        /// Defines an entity.
        /// </summary>
        [DebuggerDisplay("{DebuggerDisplayString,nq}")]
        public abstract class Entity
            : IDebuggerDisplayString,
              IEquatable<Entity>
        {
            public static bool operator ==(Entity a, Entity b)
            {
                if (ReferenceEquals(a, null) && ReferenceEquals(b, null))
                    return true;
    
                if (ReferenceEquals(a, null) || ReferenceEquals(b, null))
                    return false;
    
                return a.Equals(b);
            }
    
            public static bool operator !=(Entity a, Entity b)
                => !(a == b);
    
            protected Entity(Id id)
                => Id = id;
    
            public Id Id { get; }
    
            public override bool Equals(object @object)
            {
                if (@object == null) return false;
                if (@object is Entity entity) return Equals(entity);
                return false;
            }
    
            public bool Equals(Entity other)
            {
                if (other == null) return false;
                if (ReferenceEquals(this, other)) return true;
                if (GetType() != other.GetType()) return false;
                return Id == other.Id;
            }
    
            public override int GetHashCode()
                => $"{GetType()}{Id}".GetHashCode();
    
            public virtual string DebuggerDisplayString
                => this.CreateDebugString(x => x.Id);
    
            public override string ToString()
                => DebuggerDisplayString;
        }
    }
    

    Person (域和对其他 ValueObject 的引用可以在 https://github.com/KodeFoxx/Kf.CleanArchitectureTemplate.NetCore31/tree/master/Source/Core/Domain/Kf.CANetCore31.Core.Domain/People 找到)
    namespace Kf.CANetCore31.Core.Domain.People
    {
        [DebuggerDisplay("{DebuggerDisplayString,nq}")]
        public sealed class Person : Entity
        {
            public static Person Empty
                => new Person();
    
            public static Person Create(Name name)
                => new Person(name);
    
            public static Person Create(Id id, Name name)
                => new Person(id, name);
    
            private Person(Id id, Name name)
                : base(id)
                => Name = name;
            private Person(Name name)
                : this(Id.Empty, name)
            { }
            private Person()
                : this(Name.Empty)
            { }
    
            public Number Number
                => Number.For(this);
            public Name Name { get; }
    
            public override string DebuggerDisplayString
                => this.CreateDebugString(x => x.Number.Value, x => x.Name);
        }
    }
    

    最佳答案

    I am not aiming to have a rigid DDD implementation. So please keep this in mind when commenting or answering. The whole id behind the typed Id is for developers coming to the project they're strongly typed to use Id in all of their entities



    那么为什么不添加一个类型别名:
    using Id = System.Int64;
    

    关于c# - Entity Framework Core 中的强类型 ID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60154834/

    相关文章:

    c# - EF代码优先。相关实体未加载

    visual-studio-2012 - Visual Studio Code 和 VS 2012 可以安装在同一台计算机上吗?

    docker - Docker 容器上的 Blazor

    c# - 日期时间字段自动转换为本地(无法编辑)

    c# - 从 ConcurrentDictionary 中安全地删除列表映射

    c# - 首先创建代码,多对多,关联表中有附加字段

    c# - 如何在 MVC4 的 UserProfile 中创建自定义附加字段

    c# - Enum<T>.Parse 允许解析任何整数字符串。这是 .net core 中的错误吗?

    c# - 无法将类型对象隐式转换为 unityengine.Vector3

    c# - 应用程序验证许可证执行情况?