-
-
Notifications
You must be signed in to change notification settings - Fork 323
-
-
Notifications
You must be signed in to change notification settings - Fork 323
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Format with another type or relation by FK #526
Comments
I gues with first found a solution but I think itsn't not useful - I think better to do more flexible current format _auditContext.EntitySettings = new()
{
{
typeof(UserProfile),
new EfEntitySettings()
{
FormatProperties = new Dictionary<string, Func<object, object>>()
{
{nameof(UserProfile.UserType), val => ((UserType)val).ToString()}
}
}
}
}; |
For the format, there is a Format method on the fluent API: Audit.EntityFramework.Configuration.Setup()
.ForContext<MyContext>(config => config
.ForEntity<OrderItem>(_ => _
.Format(x => x.Price, x => x.ToString("$#.00")))); |
Well it doesn't work as expected because it use same Type as prop not object one
Something like that will helps I think public IContextEntitySetting<TEntity> Format<TProp>(Expression<Func<TEntity, TProp>> property, Func<TProp, object> format)
{
var name = GetMemberName(property);
FormatProperties[name] = entity => format.Invoke((TProp)entity);
return this;
} |
I have created PR with that change if you don't mind #527 |
Oh, you're right Of course I don't mind, thanks a lot! Will include the changes on the next release |
What is ETA for that? Any suggestion on second question? |
Maybe today. Could you elaborate a little bit more on your second question? I think I don't fully understand |
You are amazing. As for second question: public class User {
public string Name { get; set; }
public int TeacherId { get; set; } // FK to User
public User Teacher { get; set; }
} I need something like that or very close to it Format(x => x.TeacherId, t => t.Teacher.Name, (x, context) => context.Users.FirstOrDefault(u => u.Id == x.TecherId).Name) Clients be able to see not usual TeacherId from 25 to 234 as their names |
Which data provider are you using to store the audit events? |
Audit.EntityFramework |
Are you storing the audits on tables in the same database you are auditing? It sounds like the AuditEntityAction is the place to do the override of the property. For example, assuming a lot of things like you have an entity to store the audits called Audit.Core.Configuration.Setup()
.UseEntityFramework(_ => _
.AuditTypeMapper(t => typeof(UserAudit))
.AuditEntityAction<UserAudit>((ev, entry, audit) =>
{
audit.Id = 0; // Just to be sure the automatic mapping User->UserAudit should not map User.Id to UserAudit.Id
if (entry.GetEntry().Entity is User user)
{
var ctx = (MyContext)ev.GetEntityFrameworkEvent().GetDbContext();
audit.TeacherName = ctx.Teachers.First(t => t.Id == user.TeacherId).TeacherName;
}
})); |
It looks like that Audit.Core.Configuration
.AddCustomAction(ActionType.OnScopeCreated, scope =>
{
var id = Guid.NewGuid();
scope.SetCustomField("AuditScopeId", id);
}); Audit.Core.Configuration.Setup()
.UseEntityFramework(_ =>_
.AuditTypeMapper(_ => typeof(AuditLog))
.AuditEntityAction<AuditLog>(Handle)
.IgnoreMatchedProperties());
private static void Handle(AuditEvent ev, EventEntry entry, AuditLog target)
{
if (ev.CustomFields.TryGetValue("AuditScopeId", out object value))
{
target.TransactionId = (Guid)value;
}
AuditConfig config = new();
if (ev.CustomFields.TryGetValue(nameof(AuditConfig), out object configValue))
{
config = (AuditConfig)configValue;
}
target.Event = config.Event;
target.RootEntityId = config.RootEntityId;
target.RootEntityType = config.RootEntityType;
target.PerformedById = config.ResponsibleId;
target.EntityType = entry.EntityType.Name;
target.AuditDate = DateTime.UtcNow;
target.ActionType = entry.Action;
target.EntityId = entry.PrimaryKey.First().Value.ToString();
target.Changes = new();
if ((target.ActionType == "Insert"
|| target.ActionType == "Delete")
&& entry.ColumnValues != null)
{
target.Changes.AddRange(entry.ColumnValues.Select(c => new PropertyChange()
{
Name = c.Key,
New = c.Value
}));
}
if (entry.Changes != null)
{
target.Changes.AddRange(entry.Changes.Select(c => new PropertyChange()
{
Name = c.ColumnName,
New = c.NewValue,
Old = c.OriginalValue
}));
}
} |
If you really need to do it with a method like So you could do: .ForEntity<User>(cfg => cfg
.Override(u => u.UserName,
entry => ((MyContext)entry.Context).Teachers.First(t => t.Id == ((User)entry.Entity).TeacherId).TeacherName To replace the value of "UserName" column with the Teacher Name (not a very nice example, sorry) The sad part is that you'll probably need to do some casting. Do you think something like that will work for you? |
Looks not bad. You be able to grab value from entry relation or from context if it not included |
…` methods for Entity Framework config fluent API (#526)
This was implemented in version 19.4.0, please upgrade your references and re-test.
|
Great |
I have two question regarding EntityFramework for .net core 6 version
.Format<OrderItem>(x => x.Price, x => x.ToString("$#.00"));
As example for enum types which stored as int but you want to show them as string.
2. Is possible to grab more info for related object into to changes
Like I have
User -> UserProfile
UserProfile -> MentorId -> User
User -> UserGroup
If I have changed MentorId - be able to Format value to use Mentor.Name or fetch it
The text was updated successfully, but these errors were encountered: