รหัสที่พิมพ์อย่างมากใน Core Framework เอนทิตี


12

ฉันพยายามที่จะมีIdคลาสที่พิมพ์ออกมาอย่างรุนแรงซึ่งตอนนี้ถือภายใน 'ยาว' ภายใน การใช้งานด้านล่าง ปัญหาที่ฉันมีการใช้สิ่งนี้ในเอนทิตีของฉันคือEntity Frameworkให้ฉันข้อความว่ารหัสทรัพย์สินถูกแมปไปแล้ว ดูIEntityTypeConfigurationด้านล่างของฉัน

หมายเหตุ:ฉันไม่ได้มีจุดประสงค์ที่จะใช้งาน DDD อย่างเข้มงวด ดังนั้นโปรดเก็บไว้ในใจเมื่อแสดงความคิดเห็นหรือตอบ รหัสทั้งหมดที่อยู่ด้านหลังพิมพ์Idสำหรับนักพัฒนาที่มาถึงโครงการที่พวกเขาพิมพ์อย่างยิ่งที่จะใช้รหัสในเอนทิตีทั้งหมดของพวกเขาแน่นอนแปลเป็นlong(หรือBIGINT) - แต่มันชัดเจนสำหรับคนอื่น ๆ

ใต้คลาสและการกำหนดค่าซึ่งไม่ทำงาน ซื้อคืนภาคสามารถพบได้ที่https://github.com/KodeFoxx/Kf.CleanArchitectureTemplate.NetCore31 ,

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 ไม่ต้องการแมปมัน ... เมื่อพิมพ์นานก็ไม่มีปัญหา ... ประเภทอื่น ๆ ที่คุณเห็น (ด้วย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(โดเมนและการอ้างอิงไปยัง ValueObjects อื่น ๆ สามารถดูได้ที่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);
    }
}

คำตอบ:


3

ฉันไม่ได้ตั้งเป้าหมายที่จะใช้งาน DDD อย่างเข้มงวด ดังนั้นโปรดระลึกไว้เสมอเมื่อแสดงความคิดเห็นหรือตอบคำถาม รหัสทั้งหมดที่อยู่เบื้องหลังรหัสที่พิมพ์คือสำหรับนักพัฒนาที่มาถึงโครงการที่พวกเขาพิมพ์อย่างยิ่งที่จะใช้รหัสในทุกหน่วยงานของพวกเขา

ถ้าเช่นนั้นทำไมไม่เพียงเพิ่มชื่อแทนประเภท:

using Id = System.Int64;

แน่นอนว่าฉันชอบความคิด แต่ทุกครั้งที่คุณกำลังใช้ "Id" ในไฟล์. cs คุณไม่ต้องแน่ใจว่าวางคำสั่งนี้ไว้ที่ด้านบน - ในขณะที่มีคลาสที่ถูกส่งไปรอบ ๆ นอกจากนี้ฉันจะสูญเสียฟังก์ชั่นชั้นฐานอื่น ๆ เช่นId.Empty... หรือจะต้องใช้มันเป็นอย่างอื่นในวิธีการขยายแล้ว ... ฉันชอบความคิดขอบคุณสำหรับการคิดตาม หากไม่มีวิธีการแก้ปัญหาอื่นเกิดขึ้นฉันจะจัดการเรื่องนี้เพราะนี่แสดงถึงเจตนาชัดเจน
Yves Schelpe

3

ดังนั้นหลังจากค้นหามานานแล้วและพยายามหาคำตอบเพิ่มเติมฉันก็พบว่าที่นี่เป็นตอนนั้น ขอบคุณ Andrew Lock

ID ที่พิมพ์อย่างมากใน EF Core: การใช้ ID เอนทิตีที่พิมพ์อย่างรุนแรงเพื่อหลีกเลี่ยงความหลงไหลในแบบดั้งเดิม - ตอนที่ 4 : https://andrewlock.net/strongly-typed-ids-in-ef-core-using-strongly-typed-entity- รหัสเพื่อหลีกเลี่ยงดั้งเดิมครอบงำส่วน-4 /

TL; DR / บทสรุปของ Andrew ในบทความนี้ฉันอธิบายวิธีการใช้ ID ที่พิมพ์อย่างยิ่งในเอนทิตี EF Core ของคุณโดยใช้ตัวแปลงค่าและ IValueConverterSelector ที่กำหนดเอง ValueConverterSelector พื้นฐานในเฟรมเวิร์กของ EF Core นั้นใช้เพื่อลงทะเบียนการแปลงค่าในตัวทั้งหมดระหว่างประเภทดั้งเดิม โดยการได้รับจากคลาสนี้เราสามารถเพิ่มตัวแปลง ID ที่พิมพ์ลงไปในรายการนี้และรับการแปลงที่ราบรื่นตลอดการสืบค้นของ EF Core


2

ฉันคิดว่าคุณไม่มีโชค กรณีการใช้งานของคุณหายากมาก และ EF Core 3.1.1 ยังคงดิ้นรนกับการใส่ SQL ลงในฐานข้อมูลที่ไม่แตกหักยกเว้นกรณีฐานส่วนใหญ่

ดังนั้นคุณจะต้องเขียนสิ่งที่ต้องผ่านต้นไม้ LINQ และสิ่งนี้อาจเป็นงานจำนวนมหาศาลและหากคุณพบข้อผิดพลาดใน EF Core ซึ่งคุณจะต้องอธิบายให้สนุกในตั๋วของคุณ


ฉันเห็นด้วยกับกรณีการใช้งานน้อย แต่ความคิดที่อยู่ข้างหลังมันไม่ได้โง่อย่างสิ้นเชิงฉันอาจหวังว่า ... ? ถ้าเป็นเช่นนั้นโปรดแจ้งให้เราทราบ ถ้ามันโง่ (เชื่อได้ว่าไม่มากรหัสที่พิมพ์อย่างง่ายนั้นง่ายต่อการโปรแกรมในโดเมน) หรือถ้าฉันไม่พบคำตอบอย่างรวดเร็วฉันอาจใช้นามแฝงตามที่ David Browne แนะนำ - Micrososft ด้านล่าง ( stackoverflow) .com / a / 60155275/1155847 ) จนถึงตอนนี้ก็ยังดีในกรณีการใช้งานอื่น ๆ คอลเลกชันและเขตข้อมูลที่ซ่อนอยู่ใน EF Core ไม่มีข้อบกพร่องดังนั้นฉันคิดว่ามันแปลกไปเพราะฉันมีประสบการณ์ที่ดีกับผลิตภัณฑ์
Yves Schelpe

มันไม่ได้โง่ แต่ก็หายากที่ไม่เคยมีใครสนับสนุนฉันเลยและ EfCore แย่มากจนตอนนี้ฉันกำลังพยายามลบมันและย้ายกลับไปที่ Ef (ไม่ใช่แกน) เพราะฉันต้องจัดส่ง สำหรับฉัน EfCore 2.2 ทำงานได้ดีขึ้น - 3.1 เป็น 100% ไม่เป็นที่คาดการณ์เนื่องจากฉันใช้ผลลัพธ์ใน sql ที่ไม่ดีหรือ "เราไม่ได้ประเมินด้านไคลเอนต์อีกต่อไป" แม้ว่า - 2.2 จะประเมินเซิร์ฟเวอร์ได้อย่างสมบูรณ์แบบ ดังนั้นฉันจะไม่คาดหวังให้พวกเขาใช้เวลากับอะไรแบบนั้น - ในขณะที่ฟังก์ชั่นหลักของพวกเขาเสีย github.com/dotnet/efcore/issues/19830#issuecomment-584234667สำหรับรายละเอียดเพิ่มเติม
TomTom

EfCore 3.1 ใช้งานไม่ได้มีสาเหตุที่ทีม EfCore ตัดสินใจไม่ประเมินฝั่งลูกค้าอีกต่อไปพวกเขายังออกคำเตือนใน 2.2 เพื่อเตรียมคุณสำหรับการเปลี่ยนแปลงที่จะเกิดขึ้น สำหรับสิ่งนั้นฉันไม่เห็นว่าสิ่งนั้นแตกหัก สำหรับสิ่งอื่น ๆ ที่ฉันไม่สามารถแสดงความคิดเห็นได้ฉันเห็นปัญหา แต่สามารถทำงานออกมาได้โดยไม่เสียค่าใช้จ่ายใด ๆ ในอีก 3 โครงการสุดท้ายที่ฉันทำเพื่อการผลิต 2 ในนั้นคือ Dapper based, Ef based หนึ่ง ... บางทีฉันควรตั้งเป้าที่จะไปเส้นทาง dapper สำหรับอันนี้ แต่กำจัดจุดประสงค์ของการเข้าใช้งานง่ายสำหรับ devs ใหม่ : -) ... เราจะเห็น
Yves Schelpe

ปัญหาคือคำจำกัดความของการประเมินผลฝั่งเซิร์ฟเวอร์คืออะไร พวกเขายังเป่าสิ่งที่ง่ายมากที่ทำงานได้อย่างไร้ที่ติ คัดลอกฟังก์ชันการทำงานจนกว่าจะเป็น useles เราเพิ่งลบ EfCore และกลับไปที่ EF EF + บุคคลที่สามสำหรับการใช้งานทั่วโลก = ทำงาน ปัญหากับ dapper คือฉันอนุญาตให้ผู้ใช้ที่ซับซ้อนทุกคนตัดสินใจ LINQ - ฉันต้องแปลสิ่งนั้นจาก bo เป็นเคียวรีฝั่งเซิร์ฟเวอร์ ทำงานใน Ef 2.2 แล้วตอนนี้ borked โดยสิ้นเชิง
TomTom

ตกลงตอนนี้ฉันอ่านgithub.com/dotnet/efcore/issues/19679#issuecomment-583650245นี้แล้ว... ฉันเห็นว่าคุณหมายถึงอะไรคุณใช้ lib บุคคลที่สาม คุณสามารถใช้ถ้อยคำใหม่ในสิ่งที่คุณพูดเกี่ยวกับ Dapper ได้หรือไม่เพราะฉันไม่เข้าใจว่าคุณหมายถึงอะไร สำหรับฉันมันใช้งานได้ แต่มันเป็นโปรเจ็กต์ที่มีความสำคัญน้อยโดยมี 2 devs อยู่ในทีม - และมีแผ่นสำเร็จรูปจำนวนมากที่เขียนขึ้นเพื่อให้ทำงานได้อย่างมีประสิทธิภาพแน่นอน ...
Yves Schelpe
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.