Saya mencoba untuk memiliki Id
kelas yang sangat diketik , yang sekarang memegang 'panjang' secara internal. Implementasi di bawah ini. Masalah yang saya alami saat menggunakan ini di entitas saya adalah bahwa Entity Framework memberi saya pesan bahwa ID properti sudah dipetakan di atasnya. Lihat saya di IEntityTypeConfiguration
bawah ini.
Catatan: Saya tidak bermaksud memiliki implementasi DDD yang kaku. Jadi harap ingat hal ini saat berkomentar atau menjawab . Seluruh id di belakang yang diketik Id
adalah untuk pengembang yang datang ke proyek mereka diketik kuat untuk menggunakan ID di semua entitas mereka, tentu saja diterjemahkan ke long
(atau BIGINT
) - tetapi jelas kemudian untuk orang lain.
Di bawah kelas & konfigurasi, yang tidak berfungsi. Repo dapat ditemukan di https://github.com/KodeFoxx/Kf.CleanArchitectureTemplate.NetCore31 ,
Id
class at (berkomentar sekarang): https://github.com/KodeFoxx/Kf.CleanArchitectureTemplate.NetCore31/blob/master/Source/Common/Kf.CANetCore31/DomainDrivenDesign/Id.csEntity
danValueObject
kelas (di mana untukEntity
propertiId
adalah tipeId
.cs (di atas): https://github.com/KodeFoxx/Kf.CleanArchitectureTemplate.NetCore31/tree/master/Source/Common/Kf.CANetCore31/DomainDrivenDesign- Konfigurasi di: https://github.com/KodeFoxx/Kf.CleanArchitectureTemplate.NetCore31/tree/master/Source/Infrastructure/Persistence/Kf.CANetCore31.Infrastructure.Persistence.Ef/EntityTypeConfigurations
Id
implementasi kelas (ditandai sudah usang sekarang, karena saya meninggalkan ide sampai saya menemukan solusi untuk ini)
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
Saya menggunakan ketika Id tidak ditandai usang untuk entitasPerson
Sayangnya, ketika dari tipe Id, EfCore tidak ingin memetakannya ... ketika tipe lama itu tidak masalah ... Tipe yang dimiliki lainnya, seperti yang Anda lihat (dengan Name
) bekerja dengan baik.
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
kelas dasar (ketika saya masih menggunakan ID, jadi ketika itu tidak ditandai usang)
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
(domain dan referensi ke ValueObjects lain dapat ditemukan di https://github.com/KodeFoxx/Kf.CleanArchitectureTemplate.NetCore31/tree/master/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);
}
}
Id.Empty
..., atau harus mengimplementasikannya jika tidak dalam metode ekstensi kemudian ... Saya suka idenya, terima kasih untuk berpikir bersama. Jika tidak ada solusi lain yang muncul saya akan puas dengan ini, karena ini jelas menyatakan niat.