C
C#5mo ago
Ploxi

✅ [EF Core] ValueObject Mapping thinks ValueObject is a normal Entity

Problem: dotnet ef migrations add mig_somename Returns The entity type 'UpdateQueueStatus' requires a primary key to be defined. If you intended to use a keyless entity type, call 'HasNoKey' in 'OnModelCreating'. For more information on keyless entity types, see https://go.microsoft.com/fwlink/?linkid=2141943. // Mapping:
modelBuilder.Entity<UpdateQueueEntry>(builder =>
{
builder.HasKey(x => x.Id);

// x.Status is a ValueObject. The underlying value is stored in the database as a string.
// Converter is UpdateQueueStatusConverter
builder
.Property(x => x.Status)
.HasConversion<string>(new UpdateQueueStatusConverter(), new UpdateQueueStatusComparer());
});

//Converters:
public class UpdateQueueStatusConverter : ValueConverter<UpdateQueueStatus, string>
{
public UpdateQueueStatusConverter(ConverterMappingHints mappingHints = null) : base
(
v => v.Value,
v => new UpdateQueueStatus(v),
mappingHints
)
{
}
}

public class UpdateQueueStatusComparer : ValueComparer<UpdateQueueStatus>
{
public UpdateQueueStatusComparer() : base
(
equalsExpression: (c1, c2) => c1.Value == c2.Value,
hashCodeExpression: c => c.Value.GetHashCode(),
snapshotExpression: c => c.Value
)
{
}
}

public class UpdateQueueEntry : IEntity<int>, ICreationTimeTracked
{
private UpdateQueueEntry()
{
}

public int Id { get; set; }
public UpdateQueueStatus Status { get; set; }
}

public class UpdateQueueStatus
{
public static readonly UpdateQueueStatus None = new UpdateQueueStatus("None");
public static readonly UpdateQueueStatus Queued = new UpdateQueueStatus("Queued");

// more statuses...

public string Value { get; }

public UpdateQueueStatus(string value)
{
Value = value;
}

public UpdateQueueStatus()
{

}

// Removed for brevity: Implicit operators, equality, etc.

public static implicit operator string(UpdateQueueStatus status);
public static implicit operator UpdateQueueStatus(string value);
public override string ToString();
public static UpdateQueueStatus Parse(string value);
public static bool operator ==(UpdateQueueStatus left, UpdateQueueStatus right);

public static bool operator !=(UpdateQueueStatus left, UpdateQueueStatus right);

public bool Equals(UpdateQueueStatus? obj);
public override bool Equals(object? obj);
public override int GetHashCode();
}
modelBuilder.Entity<UpdateQueueEntry>(builder =>
{
builder.HasKey(x => x.Id);

// x.Status is a ValueObject. The underlying value is stored in the database as a string.
// Converter is UpdateQueueStatusConverter
builder
.Property(x => x.Status)
.HasConversion<string>(new UpdateQueueStatusConverter(), new UpdateQueueStatusComparer());
});

//Converters:
public class UpdateQueueStatusConverter : ValueConverter<UpdateQueueStatus, string>
{
public UpdateQueueStatusConverter(ConverterMappingHints mappingHints = null) : base
(
v => v.Value,
v => new UpdateQueueStatus(v),
mappingHints
)
{
}
}

public class UpdateQueueStatusComparer : ValueComparer<UpdateQueueStatus>
{
public UpdateQueueStatusComparer() : base
(
equalsExpression: (c1, c2) => c1.Value == c2.Value,
hashCodeExpression: c => c.Value.GetHashCode(),
snapshotExpression: c => c.Value
)
{
}
}

public class UpdateQueueEntry : IEntity<int>, ICreationTimeTracked
{
private UpdateQueueEntry()
{
}

public int Id { get; set; }
public UpdateQueueStatus Status { get; set; }
}

public class UpdateQueueStatus
{
public static readonly UpdateQueueStatus None = new UpdateQueueStatus("None");
public static readonly UpdateQueueStatus Queued = new UpdateQueueStatus("Queued");

// more statuses...

public string Value { get; }

public UpdateQueueStatus(string value)
{
Value = value;
}

public UpdateQueueStatus()
{

}

// Removed for brevity: Implicit operators, equality, etc.

public static implicit operator string(UpdateQueueStatus status);
public static implicit operator UpdateQueueStatus(string value);
public override string ToString();
public static UpdateQueueStatus Parse(string value);
public static bool operator ==(UpdateQueueStatus left, UpdateQueueStatus right);

public static bool operator !=(UpdateQueueStatus left, UpdateQueueStatus right);

public bool Equals(UpdateQueueStatus? obj);
public override bool Equals(object? obj);
public override int GetHashCode();
}
No description
1 Reply
Ploxi
Ploxi5mo ago
I noticed that modelBuilder._builder._entityTypes contains UpdateQueueStatus, even tho there is no dbset of it modelBuilder.Ignore<UpdateQueueStatus>(); solved the problem