Open grosch-intl opened 1 year ago
Hi Scott I have had a look to see if I can find the issue. I have been able to get the same error message though I am not sure if I have the same environment, with the problem occurring at a very low level. Could you provide an MVP DbContext along with the MVP entities and the on model creating directives for them.
Is this what you mean?
public partial class LampContext : ILampContext {
private static void BeforeSaveModifications(object? sender, EntityEntryEventArgs e) {
var state = e.Entry.State;
if (state is not EntityState.Added or EntityState.Modified)
return;
var entity = e.Entry.Entity;
var validationContext = new ValidationContext(entity);
Validator.ValidateObject(entity, validationContext, validateAllProperties: true);
if (entity is IHasTimestamps timestamp) {
var now = DateTime.UtcNow;
if (state == EntityState.Added)
timestamp.CreatedUtc = now;
timestamp.ModifiedUtc = now;
}
if (entity is IHasEtag etag)
etag.ETag = Guid.NewGuid();
}
}
public partial class LampContext : DbContext, ILampContext
{
public LampContext(DbContextOptions<LampContext> options) : base(options) {
// While ChangeTrack is non-null, it won't have a value during unit tests.
if (ChangeTracker is not null) {
ChangeTracker.StateChanged += BeforeSaveModifications; // Fired only when already tracked entities are modified.
ChangeTracker.Tracked += BeforeSaveModifications; // Fired when entities are first tracked.
}
}
public LampContext() : base() {}
public virtual DbSet<BadgeReaderData> BadgeReaderData { get; set; }
public virtual DbSet<BadgeReaderMapping> BadgeReaderMapping { get; set; }
public virtual DbSet<BadgeReaderEntitlement> BadgeReaderEntitlement { get; set; }
// Tons of others.
}
public partial class BadgeReaderEntitlement
{
[Column("id"), Required, Key]
public int Id { get; set; }
public const int ApprovalGroupPropertyMaxLength = 2000;
/// <remarks>
/// Maximum string length is 2000
/// </remarks>
[Column("approvalGroup"), Required, StringLength(ApprovalGroupPropertyMaxLength)]
public string ApprovalGroup { get; set; }
[Column("exclude"), Required]
public bool Exclude { get; set; }
public const int NamePropertyMaxLength = 255;
/// <remarks>
/// Maximum string length is 255
/// </remarks>
[Column("name"), Required, StringLength(NamePropertyMaxLength)]
public string Name { get; set; }
[Column("ownerId"), Required]
public int OwnerId { get; set; }
[Column("trainingConfigured")]
public bool? TrainingConfigured { get; set; }
#region Foreign Keys
[ForeignKey(nameof(OwnerId))]
public virtual Employee Owner { get; set; } = null!;
#endregion
}
[GeneratedCode("Scaffold", "1.0.0.0"), Table("Badge_Reader_Mapping"), PrimaryKey(nameof(BadgeReaderId), nameof(TririgaId))]
public partial class BadgeReaderMapping
{
[Column("badgeReaderId"), Required]
public int BadgeReaderId { get; set; }
[Column("tririgaId"), Required]
public int TririgaId { get; set; }
public const int BadgeReaderNamePropertyMaxLength = 200;
/// <remarks>
/// Maximum string length is 200
/// </remarks>
[Column("badgeReaderName"), Required, StringLength(BadgeReaderNamePropertyMaxLength)]
public string BadgeReaderName { get; set; }
}
Oh, also that line saying if (ChangeTracker is not null) {
is a total hack I put in place to make testing work. What's the correct way to do that?
Oh, also that line saying
if (ChangeTracker is not null) {
is a total hack I put in place to make testing work. What's the correct way to do that?
I haven't had to do this in the past. Initial thoughts: Don't change the implementation to pass a test; though it is fine to inspect the implementation and ask if it's being done as per best practice Usage of a validation context - what is it doing, is it a data access layer concern, should it be injected Setting audit properties such as created/last updated is fairly common - though I usually perform this as part of save changes
EntityFrameworkCore.Testing is basically a proxy over a testing DbContext, by default the MS in-memory provider, with mock support added for some relational operations. There will be relational operations that aren't mocked and this may be one of them.
I did make some progress, but I don't think it's for this specific issue. I was able to confirm that joining between an entity and a read only entity fails, and this is due to a query provider mismatch between the two concerns. The check happens within EFCore. I may be able to address that issue but it's not straightforward. I pushed a 4.x branch which confirmed the issue.
I'm getting this error when testing my code:
If I don't use the AddRangeToReadOnlySource methods, and instead just add it to the context and do a save first, it works fine. Is this a bug, or am I just doing something wrong?
Here's the test method, where
_context
is the entity framework database substitution, and_database
is the class with all the database calls that I need to test.It throws that error when doing the
GetEntitlementsForEhsAsync
call, which looks like this:This is the
IClassFixture
I'm using:And the relevant package versions: