将字节数组与NHibernate进行比较
本文关键字:比较 NHibernate 字节 字节数 数组 | 更新日期: 2023-09-27 17:59:02
下面的Linq到NHibernate查询将生成System.NotSupportedException
。
IEnumerable<File> FindByMd5(byte[] md5)
{
return this.Session.Query<File>().Where(f => f.Md5.SequenceEqual(md5)).ToList();
}
我应该如何使用Linq对NHibernate或QueryOver<File>()
进行此操作?
由于错误已经表明NHibernate不支持该功能。我会创建一个命名查询,并在查询中求解方程。我已经用MySQL测试了它(以常见的用户名和密码比较为例),下面的语句返回所需的行(密码是一个BINARY(32)字段):
SELECT * FROM `user` WHERE `password` = MD5('test');
使用MSSQL可以执行以下操作:
SELECT * FROM [user] WHERE [password] = HASHBYTES('MD5', 'test')
因此,要将其扩展到命名查询,您需要创建一个.hbm.xml文件,如"User.hbm.xml",其中包含以下内容:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="My.Model" namespace="My.Model">
<sql-query name="GetUserByCredentials">
<return class="My.Model.User, My.Model" />
<![CDATA[
SELECT * FROM User WHERE Username = :Username AND Password = MD5(:Password)
]]>
</sql-query>
</hibernate-mapping>
为了配置这一点,我使用了Fluent NHibernate,但类似的东西也可能只使用普通的NHibernate:
Fluently.Configure()
.Database(MySqlConfiguration.Standard
.ConnectionString(x => x.FromConnectionStringWithKey("Test"))
.AdoNetBatchSize(50))
.Cache(c => c
.UseQueryCache()
.ProviderClass<HashtableCacheProvider>())
.Mappings(m =>
{
m.FluentMappings.AddFromAssemblyOf<IHaveFluentNHibernateMappings>().Conventions.Add(ForeignKey.EndsWith("Id"));
m.HbmMappings.AddFromAssemblyOf<IHaveFluentNHibernateMappings>();
})
.BuildConfiguration();
此语句在具有名为"IHaveFluentHibernate Mappings"接口的程序集中查找".hbm.xml"文件
有了这一点,您可以在会话级别执行以下操作:
public User GetUserByCredentials(string username, string password)
{
IQuery query = Session.GetNamedQuery("GetUserByCredentials");
query.SetParameter("Username", username);
query.SetParameter("Password", password);
return query.UniqueResult<User>();
}
通过调用GetUserByCredentials方法,将执行自定义查询。
正如您所看到的,密码是一个字符串,所以您需要首先使用将MD5字节数组转换为字符串
System.Text.StringBuilder s = new System.Text.StringBuilder();
foreach (byte b in md5ByteArray)
{
s.Append(b.ToString("x2").ToLower());
}
password = s.ToString();
祝你好运!
旧Q,但仍然存在Linq问题。因此,使用NHibernate和SQLite,当与字节数组值进行比较时,可以使用查询限制或标准。
session.QueryOver<TestItem>().WhereRestrictionOn(i => i.Foo).IsBetween(aaa).And(aaa);
或
session.CreateCriteria<TestItem>().Add(Restrictions.Eq("Foo", aaa))
我通过将MD5存储为字符串解决了这个问题。
public class PersistedFile
{
public virtual int Id { get; set; }
public virtual string Path { get; set; }
public virtual string Md5 { get; set; }
}
使用以下方法保存文件:
public PersistedFile Save(string filePath)
{
using (var fileStream = new FileStream(filePath, FileMode.Open))
{
var bytes = MD5.Create().ComputeHash(fileStream);
using (var transaction = this.Session.BeginTransaction())
{
var newFile = new PersistedFile
{
Md5 = BitConverter.ToString(bytes),
Path = filePath,
};
this.Session.Save(newFile);
transaction.Commit();
return newFile;
}
}
}
文件是用这个检索的:
public IEnumerable<PersistedFile> FindByMd5(string md5)
{
using (var transaction = this.Session.BeginTransaction())
{
var files = this.Session.Query<PersistedFile>().Where(f => f.Md5 == md5).ToList();
transaction.Commit();
return files;
}
}