我正在尝试使用Asp.net身份和NHibernate。
我已经使用.NET Framework 4.5.1创建了一个新的空白Asp.net MVC网站,并且按照以下说明安装并遵循了使用nuget包NHibernate.AspNet.Identity的说明:
https://github.com/milesibastos/NHibernate.AspNet.Identity
这涉及到对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(@"~\Models\hibernate.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));
我收到以下异常:
没有持久性:IdentityTest.Models.ApplicationUser
ApplicationUser类对IdentityUser没有任何其他属性(对于Asp.net Identity的Entity Framework实现,它可以正常工作)。
谁能提供有关如何使Asp.net身份与此NuGet包一起使用的建议?
最佳答案
我对这个库非常苦恼,这使我产生疑问,为什么这是将OWIN与NHibernate一起使用的推荐库。
无论如何,为了回答您的问题,您从github网站获得的代码为库的类添加了NHibernate映射。 NHibernate没有ApplicationUser
的映射,它只有一个针对其基类的映射。 NHibernate需要实例化类的映射。这是有问题的,因为您无权访问库程序集中的映射代码,因此无法将其更改为使用ApplicationUser
类。因此,按原样使用该库来克服此问题的唯一方法是删除ApplicationUser
类并使用该库的IdentityUser
类。或者,您可以从github复制映射代码,并尝试对ApplicationUser
使用相同的映射。
而且,库代码和他为AccountController
提供的代码永远不会打开NHibernate事务,因此,即使库调用了Session.Save
和Session.Update
,数据最终也不会保存在数据库中。打开 session 后,您需要打开一个事务并将其另存为类的私有(private)字段:
transaction = session.BeginTransaction(IsolationLevel.ReadCommitted);
然后,您在
transaction.Commit()
中的操作完成执行后,需要调用AccountController
,因此您将需要覆盖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)创建用户/用户登录名时,最初创建用户/用户登录名时,将调用Update方法而不是Add。/Create导致NHibernate尝试更新不存在的实体。现在,在不进行更多研究的情况下,在
UserStore
更新方法中,我将库的代码更改为在NHibernate session 上调用SaveOrUpdate
而不是Update
,从而解决了该问题。我只对库进行了简单的测试,这些更改在更改后仍然有效,因此无法确定该库中还有多少其他运行时/逻辑错误。发现这些错误后,现在让我感到非常紧张。看起来,即使是简单的场景,也绝对没有进行任何测试。使用此库时要小心。
关于asp.net-mvc - 使用NHibernate.AspNet.Identity,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21243269/