Reputation: 33
TargetFramework: netstandard2.0
EntityFrameworkCore: 2.2.6
I have the following code in OnModelCreating:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<SlotOrder>(entity =>
{
entity.Property(e => e.Id).HasConversion(
v => v.ToString(),
v => new Guid(v));
});
modelBuilder.Entity<SlotOrderDetail>(entity =>
{
entity.Property(e => e.Id).HasConversion(
v => v.ToString(),
v => new Guid(v));
entity.HasOne<SlotOrder>()
.WithMany()
.HasForeignKey(c => c.SlotOrderId);
});
}
I do not use navigation properties and need to load all relationships of a particular entity in SaveChangesAsync. In my case if the entity is SlotOrder I need to determine that it has a child entity SlotOrderDetail:
public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
{
ChangeTracker.DetectChanges();
var utcNow = DateTime.UtcNow;
var added = ChangeTracker.Entries()
.Where(t => t.State == EntityState.Added)
.Select(t => t.Entity)
.ToList();
added.ForEach(entity =>
{
if (entity is IAuditable auditable)
{
auditable.CreatedAt = utcNow;
auditable.UpdatedAt = utcNow;
}
// var relationships = ...
});
return base.SaveChangesAsync(cancellationToken);
}
Any clue how to do that?
Upvotes: 3
Views: 743
Reputation: 1741
I don't think it's possible to do that but I just got another idea, something like this. Create new function to do SaveChanges then load all.
In any class you create you like.
public IQueryable<T> CommitLoad<T>() where T : class
{
db.SaveChanges();
var list = db.Set<T>().AsQueryable();
var key = db.Model.FindEntityType(typeof(T)).FindPrimaryKey().Properties.FirstOrDefault();
var foreignkeys = key.GetContainingPrimaryKey().GetReferencingForeignKeys();
if (foreignkeys.Count() > 0)
{
foreach (var item in foreignkeys)
list = list.Include<T>(item.DeclaringEntityType.DisplayName());
}
return list;
}
Any class or page
public IQueryable<SlotOrder> GetTest()
{
//Save record to table
//After saving record, savechanges + load all
var list = CommitLoad<SlotOrder>();
return list;
}
Here is result screenshot
Upvotes: 2
Reputation: 205539
The relationship metadata is provided by IForeignKey interface.
Given an IEntityType, there are two methods that you can use to obtain information for entity relationships - GetForeignKeys which returns the relationships where the entity is the dependent, and GetReferencingForeignKeys which return the relationships where the entity is the principal.
In your case, don't select the .Entity
property, use the EntityEntry
which gives you access to the IEntityType
via Metadata
property, e.g.
var addedEntries = ChangeTracker.Entries()
.Where(t => t.State == EntityState.Added)
.ToList();
addedEntries.ForEach(entry =>
{
if (entry.Entity is IAuditable auditable)
{
auditable.CreatedAt = utcNow;
auditable.UpdatedAt = utcNow;
}
var foreignKeys = entry.Metadata.GetForeignKeys();
var referencingForeignKeys = entry.Metadata.GetReferencingForeignKeys();
});
Upvotes: 3