Varlık Çerçevesi Çekirdeğinde Güçlü Yazılan Kimler


12

IdŞimdi 'uzun' dahili olarak tutan güçlü yazılan bir sınıf var çalışıyorum . Aşağıdaki uygulama. Varlıklarımda bunu kullanarak yaşıyorum sorun Entity Framework bana zaten özellik kimliği üzerine eşlenmiş bir mesaj verir olmasıdır. Aşağıya IEntityTypeConfigurationbakın.

Not: Katı bir DDD uygulaması hedeflemiyorum. Bu yüzden yorum yaparken veya cevaplarken bunu aklınızda bulundurun . Yazılanın arkasındaki tüm kimlik Id, projeye gelen geliştiricilere yöneliktir, elbette tüm varlıklarında Id'yi kullanmak için güçlü bir şekilde yazıldılar, elbette long(veya BIGINT) - tercüme edildi , ancak o zaman diğerleri için açık.

Sınıf ve konfigürasyonun altında, çalışmıyor. Repo https://github.com/KodeFoxx/Kf.CleanArchitectureTemplate.NetCore31 adresinde bulunabilir ,

Idsınıf uygulaması (şimdi kullanılmaz olarak işaretlendi, çünkü bunun için bir çözüm bulana kadar fikri terk ettim)

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 };
    }
}

EntityTypeConfigurationKimlik, varlık için geçersiz olarak işaretlenmediğinde kullanıyordumPerson Ne yazık ki, Id türünde, EfCore bunu eşlemek istemedi ... uzun zaman ne zaman sorun değildi ... Gördüğünüz gibi diğer sahip olunan türler (ile Name) İyi çalışmak.

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 temel sınıf (hala Id kullanıyordum, bu yüzden eski olarak işaretlenmediğinde)

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(alan adı ve diğer ValueObjects referanslarını https://github.com/KodeFoxx/Kf.CleanArchitectureTemplate.NetCore31/tree/master/Source/Core/Domain/Kf.CANetCore31.Core.Domain/People adresinde bulabilirsiniz )

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);
    }
}

Yanıtlar:


3

Katı bir DDD uygulaması hedeflemiyorum. Bu yüzden yorum yaparken veya cevaplarken bunu aklınızda bulundurun. Yazılan kimliğin arkasındaki tüm kimlik, projeye gelen geliştiricilere yönelik olarak tüm varlıklarında Kimliğini kullanmak için güçlü bir şekilde yazıldıkları içindir.

Öyleyse neden yalnızca bir tür takma adı eklemiyoruz:

using Id = System.Int64;

Tabii, fikri seviyorum. Ancak .cs dosyasındaki "Id" yi her kullanışınızda, bunu kullanarak bu ifadeyi en üste yerleştirdiğinizden emin olmak zorunda kalmazsınız - bir sınıf aktarılırken, bir tane yapmak zorunda değil misiniz? Ayrıca Id.Empty... gibi diğer temel sınıf işlevselliğini kaybedecekti ya da bir uzatma yönteminde başka türlü uygulamak zorunda kalacaktım ... Fikri sevdim, birlikte düşünmek için teşekkürler. Başka bir çözüm ortaya çıkmazsa, bunun niyetini açıkça ifade ettiği için, bunun yerine geçebilirim.
Yves Schelpe

3

Bu yüzden uzun bir süre aradıktan ve biraz daha cevap almaya çalıştıktan sonra buldum, işte o zaman. Andrew Lock'a teşekkürler.

EF Çekirdeğinde güçlü yazılan kimlikler: İlkel saplantıdan kaçınmak için güçlü yazılan kimlikler kullanma - Bölüm 4 : https://andrewlock.net/strongly-typed-ids-in-ef-core-using-strongly-typed-entity- kimlikleri-için-kaçınmak-ilkel-saplantı-parça-4 /

TL; DR / Andrew Özeti Bu yazıda EF Core varlıklarınızda güçlü dönüştürülmüş kimliklerin değer dönüştürücüler ve özel bir IValueConverterSelector kullanarak kullanılması için bir çözüm açıklıyorum. EF Çekirdek çerçevesindeki temel ValueConverterSelector, ilkel türler arasındaki tüm yerleşik değer dönüşümlerini kaydetmek için kullanılır. Bu sınıftan türeterek, güçlü bir şekilde yazılmış kimlik dönüştürücülerimizi bu listeye ekleyebilir ve EF Çekirdek sorgularımızda sorunsuz dönüşüm elde edebiliriz


2

Bence şansın yok. Kullanım durumunuz çok nadirdir. EF Core 3.1.1, SQL'i en temel durumlar dışında hiçbir şeyde bozuk olmayan veritabanına koymakla hala uğraşıyor.

Bu nedenle, LINQ ağacından geçen bir şey yazmanız gerekir ve bu büyük bir çalışmadır ve EF Core'daki hatalara rastlarsanız - ki bu da - biletlerinizde açıklamaktan zevk alırsınız.


Kullanım durumunun nadir olduğunu kabul ediyorum, ancak arkasındaki fikir tamamen aptalca değil umarım ...? Eğer öyleyse, lütfen bana bildirin. Aptalca (şimdiye kadar değil, güçlü yazılan kimliklerin etki alanında programlanması çok kolay olduğu için) veya hızlı bir cevap bulamazsam, David Browne - Micrososft tarafından önerilen bir takma ad kullanabilirim ( stackoverflow) .com / a / 60155275/1155847 ). EF Core'daki diğer kullanım durumlarında ve koleksiyonlarda ve gizli alanda şimdiye kadar iyi, böcek yok, bu yüzden garip olduğunu düşündüm, aksi takdirde ürünle sağlam bir deneyimim var.
Yves Schelpe

Kendi başına aptal değil, ama şimdiye kadar gördüğüm NO orm onu ​​destekliyor ve EfCore o kadar kötü ki şu anda onu çıkarmaya ve Ef'ye (çekirdek olmayan) geri dönmeye çalışıyorum çünkü gemiye ihtiyacım var. Benim için EfCore 2.2 daha iyi çalıştı - 3.1% 100 unutable kötü sql kullandığım herhangi bir projeksiyon veya "artık müşteri tarafı değerlendirmiyoruz" bile - 2.2 mükemmel sunucuda değerlendirmek olsa bile. Böylece, temel işlevleri bozulurken, bunun gibi şeylere zaman harcamasını beklemem. daha fazla bilgi için github.com/dotnet/efcore/issues/19830#issuecomment-584234667
TomTom

EfCore 3.1 bozuldu, EfCore ekibinin artık müşteri tarafını değerlendirmemeye karar vermesinin nedenleri var, hatta yaklaşan değişikliklere hazırlanmak için 2.2'de bu konuda uyarılar veriyorlar. Buna gelince, o şeyin kırıldığını görmüyorum. Yorum yapamayacağım diğer şeylere gelince, sorunları gördüm, ancak herhangi bir mükemmel maliyet olmadan bunları çözebildim. Öte yandan, üretim için yaptığım son 3 projede 2 tanesi Dapper tabanlı, bir Ef tabanlıydı ... Belki de bunun için dapper rotasına gitmeyi hedeflemeliyim, ancak yeni geliştiriciler için kolay giriş amacını yenmeliyim :-)... Göreceğiz.
Yves Schelpe

Sorun, sunucu tarafı değerlendirmesinin tanımıdır. Kusursuz çalışan çok basit şeylere bile esiyorlar. Kullanılana kadar işlevselliği yırttı. EfCore'u kaldırıp EF'e geri dönüyoruz. EF + global lfiltering için 3. taraf = çalışıyor. Dapper ile ilgili sorun ben her karmaşık kullanıcı LINQ karar izin - Ben bo sunucu tarafı sorguya çevirmek ZORUNDADIR. Ef 2.2'de çalışmış, şimdi tamamen dolmuş.
TomTom

Tamam, şimdi bu github.com/dotnet/efcore/issues/19679#issuecomment-583650245 okudum ... Ne demek istediğini anlıyorum Hangi üçüncü taraf lib'i kullanıyorsun? Ne demek istediğini anlamadığım için Dapper hakkında söylediklerini tekrar söyleyebilir misin? Benim için işe yaradı, ancak takımda sadece 2 devs ile düşük anahtarlı projelerdi - ve elbette verimli çalışması için yazmak için bir çok manuel
kazan plakası
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.