C# EF代码共享基类的第一个配置-->;单个配置文件
我在C#项目中首先使用EF5.0代码。我有一个基本类别,我的大多数领域模型都源自这个类别C# EF代码共享基类的第一个配置-->;单个配置文件,c#,entity-framework,entity-framework-5,code-first,entity-framework-migrations,C#,Entity Framework,Entity Framework 5,Code First,Entity Framework Migrations,我在C#项目中首先使用EF5.0代码。我有一个基本类别,我的大多数领域模型都源自这个类别 public abstract class AuditableModelBase { public Int32 CreatedByUserId { get; set; } public DateTime CreatedDate { get; set; } public virtual UserProfile CreatedByUserProfile { get; set; }
public abstract class AuditableModelBase
{
public Int32 CreatedByUserId { get; set; }
public DateTime CreatedDate { get; set; }
public virtual UserProfile CreatedByUserProfile { get; set; }
public Int32 UpdatedByUserId { get; set; }
public DateTime UpdatedDate { get; set; }
public virtual UserProfile UpdatedByUserProfile { get; set; }
public AuditableModelBase()
{
CreatedByUserId = 1;
CreatedDate = DateTime.UtcNow;
UpdatedByUserId = 1;
UpdatedDate = DateTime.UtcNow;
}
}
但是,对于每一个实体,我都必须定义特定的配置来将这些关系连接在一起
// Relationships
this.HasRequired(amb => amb.CreatedByUserProfile).WithMany().HasForeignKey(amb => amb.CreatedByUserId).WillCascadeOnDelete(false);
this.HasRequired(amb => amb.UpdatedByUserProfile).WithMany().HasForeignKey(amb => amb.UpdatedByUserId).WillCascadeOnDelete(false);
我正在寻找一种方法,只为抽象基类声明一个类似于上面的配置,而不必为我的每个实体创建一个单独的配置文件。我希望有一个名为“AuditableModelBaseMap.cs”的文件,它将具有我的配置,而不是“Entity1Map.cs”、“Entity2Map.cs”、“Entity3Map.cs”等。特别是因为所有这些文件中都有完全相同的代码
有什么建议吗
谢谢。像下面这样尝试一下,但我没有测试它。不过,如果我是你,我不会这样设计审计表
class AuditableModelBaseMap : EntityTypeConfiguration<AuditableModelBase>
{
public AuditableModelBaseMap ()
{
this.HasRequired(amb => amb.CreatedByUserProfile).WithMany().HasForeignKey(amb => amb.CreatedByUserId).WillCascadeOnDelete(false);
this.HasRequired(amb => amb.UpdatedByUserProfile).WithMany().HasForeignKey(amb => amb.UpdatedByUserId).WillCascadeOnDelete(false);
}
}
类AuditableModelBaseMap:EntityTypeConfiguration
{
公共AuditableModelBaseMap()
{
this.HasRequired(amb=>amb.CreatedByUserProfile).WithMany().HasForeignKey(amb=>amb.CreatedByUserId).WillCascadeOnDelete(false);
this.HasRequired(amb=>amb.UpdatedByUserProfile).WithMany().HasForeignKey(amb=>amb.UpdatedByUserId).WillCascadeOnDelete(false);
}
}
这是我做审计的方式
public interface IEntity
{
int Id { get; set; }
}
public interface IAuditable : IEntity
{
string UpdatedBy { get; set; }
string CreatedBy { get; set; }
DateTime CreatedDate { get; set; }
DateTime UpdateDate { get; set; }
}
Now any entity which is auditable will implement this class your context will look the following
public class MYContext : DbContext, ILicensingContext
{
private readonly IAuditLogBuilder _auditLogBuilder;
public LicensingContext()
: this(new AuditLogBuilder())
{
}
private IDbSet<Device> Devices { get; set; }
private IDbSet<AuditLog> AuditLogs { get; set; }
public MyContext(IAuditLogBuilder auditLogBuilder)
{
_auditLogBuilder = auditLogBuilder;
}
/// <summary>
/// 1. Constructs the AuditLog objects from the context
/// 2. Calls SaveChanges to save the actual object modified
/// 3. It updates the Log objects constructed in step 1 to populate the IDs returned from the Db
/// 4. Saves the AuditLogs
/// </summary>
/// <returns></returns>
public override int SaveChanges()
{
var entries = ChangeTracker.Entries<IAuditable>().ToList();
_auditLogBuilder.UpdateAuditables(entries);
IEnumerable<AuditLog> auditLogEntities = _auditLogBuilder.ConstructAuditLogs(entries).ToList();
int countOfAffectedRecords = base.SaveChanges();
_auditLogBuilder.UpdateAuditLogs(auditLogEntities);
foreach (AuditLog auditLogEntity in auditLogEntities)
{
GetDbSet<AuditLog>().Add(auditLogEntity);
}
base.SaveChanges();
return countOfAffectedRecords;
}
public IDbSet<TEntity> GetDbSet<TEntity>() where TEntity : class
{
return Set<TEntity>();
}
}
public class AuditLogBuilder : IAuditLogBuilder
{
private string _username;
private string Username
{
get
{
if (HttpContext.Current != null && HttpContext.Current.User != null)
{
_username = HttpContext.Current.User.Identity.Name;
}
if (String.IsNullOrWhiteSpace(_username))
{
_username = "Service Consumer";
}
return _username;
}
}
public IEnumerable<AuditLog> ConstructAuditLogs(IEnumerable<DbEntityEntry<IAuditable>> auditableEntities)
{
var audits = new List<AuditLog>();
if (auditableEntities != null)
{
audits.AddRange(auditableEntities
.Where(
e =>
e.State == EntityState.Modified || e.State == EntityState.Added ||
e.State == EntityState.Deleted)
.SelectMany(GetAuditLogs));
}
return audits;
}
public void UpdateAuditLogs(IEnumerable<AuditLog> auditLogEntities)
{
foreach (AuditLog auditLog in auditLogEntities)
{
auditLog.RecordId = auditLog.Entity.Id;
auditLog.UpdatedBy = auditLog.Entity.UpdatedBy;
if (String.Equals(auditLog.PropertyName, "id", StringComparison.CurrentCultureIgnoreCase))
{
auditLog.NewValue = auditLog.Entity.Id.ToString(CultureInfo.CurrentCulture);
}
}
}
public void UpdateAuditables(IEnumerable<DbEntityEntry<IAuditable>> entries)
{
if (entries != null)
{
foreach (var entry in entries)
{
entry.Entity.UpdateDate = DateTime.UtcNow;
entry.Entity.UpdatedBy = Username;
if (entry.Entity.Id == 0)
{
entry.Entity.CreatedDate = DateTime.UtcNow;
entry.Entity.CreatedBy = Username;
}
}
}
}
private static IEnumerable<AuditLog> GetAuditLogs(DbEntityEntry<IAuditable> entry)
{
var audits = new List<AuditLog>();
string entityName = ObjectContext.GetObjectType(entry.Entity.GetType()).Name;
switch (entry.State)
{
case EntityState.Added:
audits.AddRange(entry.CurrentValues.PropertyNames.Select(propertyName =>
new AuditLog
{
EntityName = entityName,
CreateDate = DateTime.UtcNow,
NewValue =
entry.CurrentValues[
propertyName] != null
? entry.CurrentValues[
propertyName].ToString()
: String.Empty,
PreviousValue = String.Empty,
PropertyName = propertyName,
Entity = entry.Entity,
Action = Actions.Create.ToString()
}));
break;
case EntityState.Deleted:
audits.AddRange(entry.OriginalValues.PropertyNames.Select(propertyName =>
new AuditLog
{
EntityName = entityName,
CreateDate = DateTime.UtcNow,
NewValue = String.Empty,
PreviousValue =
entry.OriginalValues[
propertyName] != null
? entry.OriginalValues[
propertyName].ToString
()
: String.Empty,
PropertyName = propertyName,
Entity = entry.Entity,
Action = Actions.Delete.ToString()
}));
break;
case EntityState.Modified:
audits.AddRange(entry.OriginalValues.PropertyNames.
Where(
propertyName =>
!Equals(entry.OriginalValues[propertyName],
entry.CurrentValues[propertyName]))
.Select(propertyName =>
new AuditLog
{
EntityName = entityName,
CreateDate = DateTime.UtcNow,
NewValue =
entry.CurrentValues[propertyName] != null
? entry.CurrentValues[propertyName].ToString()
: String.Empty,
PreviousValue =
entry.OriginalValues[propertyName] != null
? entry.OriginalValues[propertyName].ToString()
: String.Empty,
PropertyName = propertyName,
Entity = entry.Entity,
Action = Actions.Update.ToString()
}));
break;
}
return audits;
}
}
公共接口的可扩展性
{
int Id{get;set;}
}
公共接口IAuditable:可编辑性
{
由{get;set;}更新的字符串
字符串CreatedBy{get;set;}
DateTime CreatedDate{get;set;}
DateTime UpdateDate{get;set;}
}
现在,任何可审核的实体都将实现这个类,您的上下文将如下所示
公共类MYContext:DbContext、ILicensingContext
{
私有只读IAuditLogBuilder\u auditLogBuilder;
公共许可上下文()
:此(新的AuditLogBuilder())
{
}
专用IDbSet设备{get;set;}
私有IDbSet审核日志{get;set;}
公共MyContext(IAuditLogBuilder auditLogBuilder)
{
_auditLogBuilder=auditLogBuilder;
}
///
///1.从上下文构造AuditLog对象
///2.调用SaveChanges以保存实际修改的对象
///3.它更新步骤1中构造的日志对象,以填充从Db返回的ID
///4.保存审核日志
///
///
公共覆盖int SaveChanges()
{
var entries=ChangeTracker.entries().ToList();
_auditLogBuilder.UpdateAuditables(条目);
IEnumerable auditLogEntities=_auditLogBuilder.ConstructAuditLogs(entries.ToList();
int countOfAffectedRecords=base.SaveChanges();
_auditLogBuilder.UpdateAuditLogs(auditLogEntities);
foreach(auditLogEntities中的AuditLog auditLogEntity)
{
GetDbSet().Add(auditLogEntity);
}
base.SaveChanges();
返回受影响记录的计数;
}
public IDbSet GetDbSet(),其中tenty:class
{
返回集();
}
}
公共类AuditLogBuilder:IAAuditLogBuilder
{
私有字符串\u用户名;
私有字符串用户名
{
得到
{
if(HttpContext.Current!=null&&HttpContext.Current.User!=null)
{
_username=HttpContext.Current.User.Identity.Name;
}
if(String.IsNullOrWhiteSpace(_username))
{
_用户名=“服务消费者”;
}
返回_用户名;
}
}
公共IEnumerable ConstructionAuditLogs(IEnumerable auditableEntities)
{
var审计=新列表();
if(auditableEntities!=null)
{
审计。添加范围(可审计实体)
.在哪里(
e=>
e、 State==EntityState.Modified | | e.State==EntityState.Added||
e、 State==EntityState.Deleted)
.SelectMany(GetAuditLogs));
}
退货审核;
}
public void UpdateAuditLogs(IEnumerable auditLogEntities)
{
foreach(AuditLog实体中的AuditLog AuditLog)
{
auditLog.RecordId=auditLog.Entity.Id;
auditLog.UpdatedBy=auditLog.Entity.UpdatedBy;
if(String.Equals(auditLog.PropertyName,“id”,StringComparison.CurrentCultureIgnoreCase))
{
auditLog.NewValue=auditLog.Entity.Id.ToString(CultureInfo.CurrentCulture);
}
}
}
public void UpdateAuditables(IEnumerable条目)
{
if(条目!=null)
{
foreach(分录中的var分录)
{
entry.Entity.UpdateDate=DateTime.UtcNow;
entry.Entity.UpdatedBy=用户名;
if(entry.Entity.Id==0)
{
entry.Entity.CreatedDate=DateTime.UtcNow;
entry.Entity.CreatedBy=用户名;
}
}
}
}
私有静态IEnumerable GetAuditLogs(DbEntityEntry)
{
变量a
public class AuditableModelBaseMap : EntityTypeConfiguration<AuditableModelBase>
{
public AuditableModelBaseMap()
{
this.HasRequired(amb => amb.CreatedByUserProfile).WithMany().HasForeignKey(amb => amb.CreatedByUserId).WillCascadeOnDelete(false);
this.HasRequired(amb => amb.UpdatedByUserProfile).WithMany().HasForeignKey(amb => amb.UpdatedByUserId).WillCascadeOnDelete(false);
}
}