Problema della parte 2, che continua da qui: EntityFramework Core: record di aggiornamento non riuscito con DbUpdateConcurrencyException
Errore:
Il tipo derivato 'BinaryFile' non può avere KeyAttribute sulla proprietà 'Id' poiché la chiave primaria può essere dichiarata solo sul tipo root.
Sto cercando di rendere l'eredità per le mie entità il più possibile, quindi rimuoverò il più possibile la duplicazione.
La mia struttura ereditaria:
public interface IEntityMinimum
{
bool IsDeleted { get; set; }
byte[] Version { get; set; }
string CreatedBy { get; set; }
}
public class EntityMinimum : IEntityMinimum
{
public bool IsDeleted { get; set; }
[Timestamp]
public byte[] Version { get; set; }
public string CreatedBy { get; set; }
}
public interface IEntity : IEntityMinimum
{
object Id { get; set; }
DateTime CreatedDate { get; set; }
DateTime? ModifiedDate { get; set; }
string ModifiedBy { get; set; }
}
public interface IEntity<T> : IEntity
{
new T Id { get; set; }
}
public abstract class Entity<T> : EntityMinimum, IEntity<T>
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public T Id { get; set; }
object IEntity.Id
{
get => Id;
set => throw new NotImplementedException();
}
private DateTime? _createdDate;
[DataType(DataType.DateTime)]
public DateTime CreatedDate
{
get => _createdDate ?? DateTime.UtcNow;
set => _createdDate = value;
}
[DataType(DataType.DateTime)]
public DateTime? ModifiedDate { get; set; }
public string ModifiedBy { get; set; }
}
public class EntityMaximum : Entity<int>
{
public bool IsActive { get; set; }
}
public class BinaryFile : EntityMaximum
{
public string Name { get; set; }
public string UniqueName { get; set; }
public Guid UniqueId { get; set; }
public byte[] Content { get; set; }
public virtual ICollection<Campaign> Campaigns { get; set; }
}
isConcurrencyToken
questo errore quando utilizzo Fluent API per disabilitare isConcurrencyToken
nel campo Version
per la classe EntityMinimum
questo modo:
// https://stackoverflow.com/questions/44009020/entity-framework-isrowversion-without-concurrency-check
builder.Entity<EntityMinimum>().Property(x => x.Version).IsRowVersion().IsConcurrencyToken(false);
Questo è necessario perché ho avuto un altro problema se non disattivo isConcurrencyToken
nel campo Version
:
Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: l'operazione del database dovrebbe interessare 1 riga (e), ma in realtà ha interessato 0 righe (s). I dati potrebbero essere stati modificati o cancellati da quando le entità sono state caricate.
Se rimuovo la fluente configurazione API, funziona, ma non si aggiorna a causa del campo Version
che ha l'attributo [TimeStamp]
.
Ho questo campo [TimeStamp]
Version
in EntityMinimum
per aggiungere la Version
a ogni tabella, quindi posso utilizzare TimeStamp
per scopi di sincronizzazione tra dati mobili e web.
Sto facendo correttamente questa struttura, o dovrei sbarazzarmi della versione [TimeStamp] byte[] Version
e usare solo la stringa Version
e salvare i tick DateTime
in essa per scopi di sincronizzazione?
Il problema è che la chiamata
builder.Entity<EntityMinimum>()
segna la classe EntityMinimum
come entità (parte della strategia di ereditarietà di EF Core), mentre, come ho capito, si utilizza la gerarchia delle classi di base solo a scopo di implementazione.
Invece, è possibile utilizzare i servizi di metadati del modello EF Core per disattivare IsConcurrencyToken
per la proprietà Version
di qualsiasi entità reale derivata da EntityMinimum
questo modo:
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
if (typeof(EntityMinimum).IsAssignableFrom(entityType.ClrType))
entityType.FindProperty("Version").IsConcurrencyToken = false;
}