我正在尝试使用asp.net身份和nhibernate。
我已经使用.NET Framework 4.5.1创建了一个新的空白ASP.NET MVC站点,并已安装并遵循了使用Nuget Package Nhibernate.aspnate.Sternity的说明,如下所述:
https://github.com/milesibastos/nhibernate.aspnet.sideity
涉及对accountController类默认构造函数进行以下更改:
var mapper = new ModelMapper();
mapper.AddMapping<IdentityUserMap>();
mapper.AddMapping<IdentityRoleMap>();
mapper.AddMapping<IdentityUserClaimMap>();
mapper.AddMapping<IdentityUserLoginMap>();
var mapping = mapper.CompileMappingForAllExplicitlyAddedEntities();
var configuration = new Configuration();
configuration.Configure(System.Web.HttpContext.Current.Server.MapPath(@"~Modelshibernate.cfg.xml"));
configuration.AddDeserializedMapping(mapping, null);
var schema = new SchemaExport(configuration);
schema.Create(true, true);
var factory = configuration.BuildSessionFactory();
var session = factory.OpenSession();
UserManager = new UserManager<ApplicationUser>(
new UserStore<ApplicationUser>(session));
我得到以下例外:
没有迫害:dentitytest.models.applicationuser
ApplicationUser类没有任何其他属性(对于ASP.NET身份的实体框架实现)。
任何人都可以提供有关我如何获得ASP.NET身份的建议吗?
我在这个库中非常挣扎,这让我质疑为什么这是将Owin与Nhibernate一起使用的推荐库。
无论如何,要回答您的问题,您从Github网站获得的代码添加了图书馆类的NHibernate映射。NHibernate没有ApplicationUser
的映射,它的基类仅具有映射。Nhibernate需要为实例化类的映射。这是有问题的,因为您无法访问库的组件中的映射代码,因此您无法将其更改以使用ApplicationUser
类。因此,使用库以原样的库来克服此问题的唯一方法是删除ApplicationUser
类并使用库的IdentityUser
类。或者,您可以从GitHub复制映射代码,并尝试使用ApplicationUser
的相同映射。
另外,他为AccountController
提供的库代码和代码永远不会打开NHIBERNATE事务,因此,即使库调用Session.Save
和Session.Update
,数据最终也不会保存在数据库中。打开会话后,您需要打开交易并将其保存为班上的私人字段:
transaction = session.BeginTransaction(IsolationLevel.ReadCommitted);
然后,您需要在AccountController
完成操作后调用transaction.Commit()
,因此您需要覆盖OnResultExecuted
:
protected override void OnResultExecuted(ResultExecutedContext filterContext)
{
transaction.Commit();
}
请记住,此示例过于简单,在生产应用程序中,您需要有错误检查在哪里回滚而不是提交如果有错误,则需要正确关闭/处理所有内容,等等。
此外,即使您解决了这些问题,图书馆还有其他问题。我最终不得不从github下载源,以便可以修改库以使用它。库的代码中至少还有3个其他公然错误:
1)在 nhibernate.aspnet.Identity.userstore :
public virtual async Task<TUser> FindAsync(UserLoginInfo login)
{
this.ThrowIfDisposed();
if (login == null)
throw new ArgumentNullException("login");
IdentityUser entity = await Task.FromResult(Queryable
.FirstOrDefault<IdentityUser>(
(IQueryable<IdentityUser>)Queryable.Select<IdentityUserLogin, IdentityUser>(
Queryable.Where<IdentityUserLogin>(
// This line attempts to query nhibernate for the built in asp.net
// UserLoginInfo class and then cast it to the NHibernate version IdentityUserLogin,
// which always causes a runtime error. UserLoginInfo needs to be replaced
// with IdentityUserLogin
(IQueryable<IdentityUserLogin>)this.Context.Query<UserLoginInfo>(), (Expression<Func<IdentityUserLogin, bool>>)(l => l.LoginProvider == login.LoginProvider && l.ProviderKey == login.ProviderKey)),
(Expression<Func<IdentityUserLogin, IdentityUser>>)(l => l.User))));
return entity as TUser;
}
2)在 nhibernate.aspnet.Identity.domainModel.valueObject :
protected override IEnumerable<PropertyInfo> GetTypeSpecificSignatureProperties()
{
var invalidlyDecoratedProperties =
this.GetType().GetProperties().Where(
p => Attribute.IsDefined(p, typeof(DomainSignatureAttribute), true));
string message = "Properties were found within " + this.GetType() +
@" having the
[DomainSignature] attribute. The domain signature of a value object includes all
of the properties of the object by convention; consequently, adding [DomainSignature]
to the properties of a value object's properties is misleading and should be removed.
Alternatively, you can inherit from Entity if that fits your needs better.";
// This line is saying, 'If there are no invalidly decorated properties,
// throw an exception'..... which obviously should be the opposite,
// remove the negation (!)
if (!invalidlyDecoratedProperties.Any())
throw new InvalidOperationException(message);
return this.GetType().GetProperties();
}
3)在 nhibernate.aspnet.Identity.USERSTORE 中:至少在最初创建用户/用户登录时,至少在使用外部提供商(例如Facebook)创建用户/用户登录时,调用更新方法,而不是添加/创建引起nHibernate以尝试更新不存在的实体。目前,在UserStore
更新方法中,我更改了库的代码,以在NHIBERNATE会话上调用SaveOrUpdate
,而不是解决问题的Update
。
我只对我更改后有效的库进行了简单的测试,因此在此库中没有任何其他运行时/逻辑错误。找到这些错误后,我现在真的很紧张。似乎甚至没有简单的场景都没有进行测试。谨慎使用此库。
我也很难使用nhibernate.aspnet.Identity。我发现,使用NHibernate进行自己的实现要容易得多,我将其变成了一个最小的工作示例:
https://github.com/martineden/nhibernate.aspnet.identity.example
它们的关键部分是使用NHibernate会话进行持久性的IUserStore<TUser, TKey>
和IUserPasswordStore<TUser, TKey>
的简单实现。然后,这只是写一些胶水来告诉Owin使用该代码的问题。