我正在与Audit.NET合作,这是一个开源审核框架,它为实体框架和DbContext
提供了扩展:AuditDbContext.cs
// Implements DbContext
public abstract partial class AuditDbContext : DbContext
我想在我的项目中使用此Entity Framework扩展实现Audit.NET,因为它会自动执行我需要手动执行的许多步骤(我可以手动使用Audit.NET实体框架扩展)。我遇到的问题是我的解决方案存储库实现了IdentityDbContext
,当然这也是DbContext
的实现。
// Implements IdentityDbContext
public class MyDataContext : IdentityDbContext<ApplicationUser>
{
public MyDataContext() : base("DefaultConnection") { }
...
没有现有AuditDbContext
实施IdentityDbContext
。
我似乎无法想出一种干净的方式将这两者混合在一起并使我的存储库使用AuditDbContext
,特别是考虑到AuditDbContext
具有受保护的构造函数,并且DbContext
和IdentityDbContext
有protected
个方法。我尝试创建一个名为AuditIdentityDbContext
的合成,其中每个上下文都有private
个副本,但我无法通过这样做来完成所有接口。
由于DbContext
成员,似乎需要继承上述所有3 protected
种类型。在我的职业生涯中,我觉得多次继承可能在这种情况下实际上有所帮助,但鉴于这不可能,最好的选择是什么呢?
我唯一能想到的是创建一个继承自AuditDbContext
或IdentityDbContext<TUser>
的新类,并手动实现剩下的任何内容以匹配另一个的功能。虽然没有可以实现的接口类,所以我很确定这不会起作用。我觉得我必须忽略一些东西。
答案 0 :(得分:3)
哎哟!
但你仍然可以找到出路。 IdentityDbContext
没什么特别的,甚至没有接口!所以你需要做的就是告诉你自己的DbContext关于用户和角色并添加一些验证。
IdentityDbContext
的肉是这样的:
public virtual IDbSet<TUser> Users { get; set; }
public virtual IDbSet<TRole> Roles { get; set; }
public bool RequireUniqueEmail { get; set; } // this might not be important for you
用您自己的ApplicationUser
和ApplicationRole
替换泛型参数(这两个类都可以从Identity提供的类继承)
添加或混合您自己的方法:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
if (modelBuilder == null)
{
throw new ArgumentNullException("modelBuilder");
}
// Needed to ensure subclasses share the same table
var user = modelBuilder.Entity<TUser>()
.ToTable("AspNetUsers");
user.HasMany(u => u.Roles).WithRequired().HasForeignKey(ur => ur.UserId);
user.HasMany(u => u.Claims).WithRequired().HasForeignKey(uc => uc.UserId);
user.HasMany(u => u.Logins).WithRequired().HasForeignKey(ul => ul.UserId);
user.Property(u => u.UserName)
.IsRequired()
.HasMaxLength(256)
.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("UserNameIndex") { IsUnique = true }));
// CONSIDER: u.Email is Required if set on options?
user.Property(u => u.Email).HasMaxLength(256);
modelBuilder.Entity<TUserRole>()
.HasKey(r => new { r.UserId, r.RoleId })
.ToTable("AspNetUserRoles");
modelBuilder.Entity<TUserLogin>()
.HasKey(l => new { l.LoginProvider, l.ProviderKey, l.UserId })
.ToTable("AspNetUserLogins");
modelBuilder.Entity<TUserClaim>()
.ToTable("AspNetUserClaims");
var role = modelBuilder.Entity<TRole>()
.ToTable("AspNetRoles");
role.Property(r => r.Name)
.IsRequired()
.HasMaxLength(256)
.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("RoleNameIndex") { IsUnique = true }));
role.HasMany(r => r.Users).WithRequired().HasForeignKey(ur => ur.RoleId);
}
并且
protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry,
IDictionary<object, object> items)
{
if (entityEntry != null && entityEntry.State == EntityState.Added)
{
var errors = new List<DbValidationError>();
var user = entityEntry.Entity as TUser;
//check for uniqueness of user name and email
if (user != null)
{
if (Users.Any(u => String.Equals(u.UserName, user.UserName)))
{
errors.Add(new DbValidationError("User",
String.Format(CultureInfo.CurrentCulture, IdentityResources.DuplicateUserName, user.UserName)));
}
if (RequireUniqueEmail && Users.Any(u => String.Equals(u.Email, user.Email)))
{
errors.Add(new DbValidationError("User",
String.Format(CultureInfo.CurrentCulture, IdentityResources.DuplicateEmail, user.Email)));
}
}
else
{
var role = entityEntry.Entity as TRole;
//check for uniqueness of role name
if (role != null && Roles.Any(r => String.Equals(r.Name, role.Name)))
{
errors.Add(new DbValidationError("Role",
String.Format(CultureInfo.CurrentCulture, IdentityResources.RoleAlreadyExists, role.Name)));
}
}
if (errors.Any())
{
return new DbEntityValidationResult(entityEntry, errors);
}
}
return base.ValidateEntity(entityEntry, items);
}
(taken from source code as is)
当您需要创建ApplicationUserManager
时,需要IUserStore
并且用户存储的默认实现需要DbContext
,因此您可以提供实际从AuditDbContext
<继承的DbContext / p>
这应该可以做到,而不必双重继承。 Viva开源!
答案 1 :(得分:1)
我遇到过与我合作过的项目类似的问题。我们最终做的是做两个单独的DbContext
但是它们共享相同的数据库。
查看此答案,了解如何访问Users
和Roles
属性,以及Claims
,Logins
和UserRoles
来自{{ 1}}
答案 2 :(得分:1)
@trailmax解决方案应该有效,但我已更新Audit.NET库以包含对%f = 101.000000
%.f = 101
%.02f = 101.00
的支持。
我们提供了一个新类AuditIdentityDbContext,您可以将上下文更改为继承该类。
您应该将代码更改为:
IdentityDbContext
注意:我是图书馆老板