एंटिटी फ्रेमवर्क कोर में मजबूत टाइप किए गए Ids


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मैं उपयोग कर रहा था जब आईडी इकाई के लिए अप्रचलित चिह्नित नहीं हैPerson दुर्भाग्य से, हालांकि, जब ईद का प्रकार होता है, तो 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 आधार वर्ग (जब मैं अभी भी आईडी का उपयोग कर रहा था, इसलिए जब यह अप्रचलित नहीं था)

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;

ज़रूर, मुझे यह विचार पसंद है। लेकिन हर बार जब आप एक .cs फ़ाइल में "Id" का उपयोग कर रहे होंगे, तो क्या आपको यह सुनिश्चित करने की ज़रूरत नहीं होगी कि आप इसे ऊपर दिए गए स्टेटमेंट का उपयोग कर सकें - जबकि कक्षा पास होने के बाद, किसी को पास नहीं करना है? इसके अलावा, मैं अन्य बेस क्लास कार्यक्षमता को खो दूंगा जैसे Id.Empty..., या फिर इसे विस्तार विधि में अन्यथा लागू करना होगा ... मुझे यह विचार पसंद है, साथ में सोचने के लिए thx। यदि कोई अन्य समाधान नहीं आता है, तो मैं इसके लिए समझौता करूंगा, क्योंकि यह स्पष्ट रूप से इरादा रखता है।
यवेस शेलेप

3

इसलिए लंबे समय तक खोज करने के बाद, और कुछ और जवाब पाने की कोशिश करते हुए, मैंने इसे पाया, यहाँ यह तब है। एंड्रयू लॉक को धन्यवाद।

EF कोर में मजबूत टाइप आईडी : आदिम जुनून से बचने के लिए दृढ़ता से टाइप की गई इकाई आईडी का उपयोग करना - भाग 4 : https://andrewlock.net/strongly-typed-ids-in-ef-using-strongly-typed-entity- आईडी करने वाली बचने-आदिम-जुनून-भाग-4 /

TL, DR / एंड्रयू का सारांश इस पोस्ट में मैं मूल्य कन्वर्टर्स और एक कस्टम IValueConverterSelector का उपयोग करके अपने EF कोर संस्थाओं में जोरदार टाइप आईडी का उपयोग करने के लिए एक समाधान का वर्णन करता हूं। EF कोर ढांचे में आधार ValueConverterSelector का उपयोग आदिम प्रकारों के बीच सभी अंतर्निहित मूल्य रूपांतरणों को पंजीकृत करने के लिए किया जाता है। इस वर्ग से प्राप्त करके, हम अपनी दृढ़ता से टाइप की गई आईडी कन्वर्टर्स को इस सूची में जोड़ सकते हैं, और हमारे EF कोर प्रश्नों में सहज रूपांतरण प्राप्त कर सकते हैं


2

मुझे लगता है कि आप भाग्य से बाहर हैं। आपका उपयोग मामला अत्यंत दुर्लभ है। और EF Core 3.1.1 डेटाबेस पर SQL डालने के साथ अभी भी संघर्ष कर रहा है जो कि अधिकांश आधार मामलों को छोड़कर किसी भी चीज़ में टूटा नहीं है।

तो, आपको कुछ लिखना होगा जो LINQ पेड़ से गुजरता है और यह संभावना काम की एक जबरदस्त मात्रा है, और यदि आप EF Core पर बगों पर ठोकर खाते हैं - जो कि आप करेंगे - जो आपके टिकटों में यह समझाते हुए मज़ेदार है।


मैं सहमत हूं कि उपयोग का मामला दुर्लभ है, लेकिन इसके पीछे का विचार पूरी तरह से बेवकूफ नहीं है जो मैं आशा कर सकता हूं ...? यदि हां, तो कृपया मुझे बताएं। यदि यह बेवकूफ है (अब तक नहीं राजी कर लिया, के रूप में दृढ़ता से टाइप किया आईडी डोमेन के साथ कार्यक्रम के लिए इतना आसान कर रहे हैं), या अगर मैं एक जवाब नहीं मिल रहा है जल्दी से मैं एक उपनाम का उपयोग कर सकते के रूप में डेविड ब्राउन ने सुझाव दिया - (नीचे Micrososft stackoverflow .com / a / 60155275/1155847 )। अब तक अन्य उपयोग के मामलों में इतना अच्छा है, और ईएफ कोर में संग्रह और छिपे हुए क्षेत्र, कोई बग नहीं है, इसलिए मैंने सोचा कि यह अजीब है, क्योंकि अन्यथा मेरे पास उत्पाद के साथ एक अच्छा अनुभव है।
यवेस शेलेप

यह प्रति बेवकूफ नहीं है, लेकिन यह दुर्लभ है कि NO orm मैंने कभी देखा है इसका समर्थन करता है और EfCore इतना बुरा है कि अभी मैं इसे हटाने और Ef (गैर कोर) में वापस जाने पर काम कर रहा हूं क्योंकि मुझे जहाज करने की आवश्यकता है। मेरे लिए EfCore 2.2 ने बेहतर काम किया - 3.1 किसी भी प्रोजेक्शन के रूप में 100% अप्राप्य है जो मैं खराब एसक्यूएल में परिणामों का उपयोग करता हूं या "हम ग्राहक पक्ष का मूल्यांकन नहीं करते हैं" भले ही - 2.2 सर्वर पर पूरी तरह से मूल्यांकन किया हो। इसलिए, मैं उनसे इस तरह के सामान पर समय बिताने की उम्मीद नहीं करूंगा - जबकि उनके मूल कार्य टूट गए हैं। अधिक जानकारी के लिए github.com/dotnet/efcore/issues/19830#issuecomment-584234667
TomTom

EfCore 3.1 टूट गया है, ऐसे कारण हैं कि EfCore टीम ने ग्राहक पक्ष का मूल्यांकन नहीं करने का फैसला किया, वे आगामी परिवर्तनों के लिए आपको तैयार करने के लिए 2.2 में इसके बारे में चेतावनी भी जारी करते हैं। उस के लिए, मुझे नहीं लगता कि वह विशेष चीज टूटी हुई है। अन्य सामानों के लिए जैसा कि मैं टिप्पणी नहीं कर सकता, मैंने मुद्दों को देखा है, लेकिन उन्हें बिना किसी पूर्ण लागत के काम करने में सक्षम किया गया है। दूसरी ओर, पिछले 3 प्रोजेक्ट्स पर, मैंने उनमें से 2 प्रोडक्शन के लिए किए थे, डॅपर बेस्ड थे, एक Ef बेस्ड था ... हो सकता है कि मुझे इसके लिए डैपर रूट पर जाने का लक्ष्य बनाना चाहिए, लेकिन नए देवों के लिए आसान एंट्री का उद्देश्य :-)... हम देखेंगे।
यवेस शेलेप

समस्या यह है कि सर्वर साइड मूल्यांकन की परिभाषा क्या है। यहां तक ​​कि बहुत ही साधारण सामान पर भी झटका दें जो निर्दोष रूप से काम करता है। जब तक यह useles था कार्यक्षमता बाहर भेज दिया। हम अभी EfCore को हटाते हैं और EF पर वापस जाते हैं। वैश्विक lfiltering = काम करने के लिए EF + 3rd पार्टी। डैपर के साथ समस्या यह है कि मैं हर जटिल उपयोगकर्ता को LINQ का फैसला करने की अनुमति देता हूं - मैं अनुवाद करना चाहता हूं कि बो से सर्वर साइड क्वेरी में। ईएफ 2.2 में काम किया, अब पूरी तरह से बोर हो गया।
टॉमटॉम

ठीक है, मैंने अब इस github.com/dotnet/efcore/issues/19679#issuecomment-583650245 को पढ़ा ... मैं देख रहा हूं कि आपका क्या मतलब है कि आप तब किस पार्टी के लिब का इस्तेमाल कर रहे हैं? क्या आपने डॅपर के बारे में जो कुछ भी कहा है, क्या आप उसे समझ सकते हैं, क्योंकि मुझे समझ नहीं आया कि आपका क्या मतलब है। मेरे लिए यह काम किया है, लेकिन यह ऐसी परियोजनाएं थीं जो टीम पर केवल 2 देवों के साथ कम महत्वपूर्ण थीं - और मैन्युअल
बायलरप्लेट का
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.