Why is EF Core trying to insert nulls when using custom ValueGenerator?
I have a custom ValueGenerator as follows:
public class UtcDateTimeGenerator : ValueGenerator<DateTime>
{
public override DateTime Next(EntityEntry entry)
{
// This method never seems to be called
return DateTime.UtcNow;
}
protected override object NextValue(EntityEntry entry)
{
// This one is called.
return DateTime.UtcNow;
}
public override bool GeneratesTemporaryValues => false;
}
On my entity's IEntityTypeConfiguration
I have this:
builder.Property(x => x.Created)
.ValueGeneratedOnAdd()
.HasValueGenerator<UtcDateTimeGenerator>()
.IsRequired();
I have a generic repository:
public class Repository<TEntity> : IRepository<TEntity>
where TEntity : class
{
private readonly EmpiresDbContext _dbContext;
private readonly DbSet<TEntity> _table;
public Repository(EmpiresDbContext dbContext)
{
_dbContext = dbContext;
_table = _dbContext.Set<TEntity>();
}
public async Task<IQueryable<TEntity>> GetQueryAsync()
{
return _table;
}
public async Task<TEntity> GetByIdAsync(object id)
{
return await _table.FindAsync(id).ConfigureAwait(false);
}
public void Insert(TEntity obj)
{
_table.Add(obj);
}
public void Update(TEntity obj)
{
_table.Attach(obj);
_dbContext.Entry(obj).State = EntityState.Modified;
}
public async Task DeleteAsync(object id)
{
var existing = await _table.FindAsync(id).ConfigureAwait(false);
_table.Remove(existing);
}
public async Task SaveAsync()
{
await _dbContext.SaveChangesAsync().ConfigureAwait(false);
}
public IDatabaseTransaction StartTransaction()
{
return new DatabaseTransaction(_dbContext);
}
}
When I call Insert()
I have used the debugger to verify that the call to _table.Add(obj);
does in fact call the protected override object NextValue(EntityEntry entry)
method on the UtcDateTimeGenerator
, and after the call to _table.Add(obj);
I can inspect the obj
and see that the Created
property has a value.
However, when public async Task SaveAsync()
calls await _dbContext.SaveChangesAsync().ConfigureAwait(false);
I get an exception
SqlException: Cannot insert the value NULL into column 'Created'
Insert()
and SaveAsync()
are called from within a service using the following code:
var player = new Player(externalId, displayName, email); // The entity we're creating
await using (var transaction = _repository.StartTransaction())
{
try
{
_repository.Insert(player);
// TODO Add any other new player setup here
await _repository.SaveAsync().ConfigureAwait(false);
await transaction.CommitAsync().ConfigureAwait(false);
}
catch
{
await transaction.RollbackAsync().ConfigureAwait(false);
throw;
}
}
DatabaseTransaction
is as follows:
public sealed class DatabaseTransaction : IDatabaseTransaction
{
private readonly IDbContextTransaction _transaction;
public DatabaseTransaction(EmpiresDbContext dbContext)
{
_transaction = dbContext.Database.BeginTransaction();
}
public void Commit()
{
_transaction.Commit();
}
public void Rollback()
{
_transaction.Rollback();
}
public async Task CommitAsync()
{
await _transaction.CommitAsync();
}
public async Task RollbackAsync()
{
await _transaction.RollbackAsync();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private bool _disposed = false;
private void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
_transaction?.Dispose();
}
_disposed = true;
}
public ValueTask DisposeAsync()
{
try
{
Dispose();
return default;
}
catch (Exception exception)
{
return new ValueTask(Task.FromException(exception));
}
}
}
from Recent Questions - Stack Overflow https://ift.tt/2Yx1XIM
https://ift.tt/eA8V8J
Comments
Post a Comment