我正在尝试使用 Fluent NHibernate 迁移需要“处理”部分数据库的数据库。源数据库是一个 MS Access 数据库,我当前使用的表是一个带有 OLE 对象字段的表。目标数据库是 MS SQL Server Express 数据库。
在实体中,我只是将这个字段定义为 byte[] 但是在加载时,即使只是为单个记录加载单个字段,我也会遇到 System.OutOfMemoryException
byte[] test = aSession.Query<Entities.Access.Revision>().Where(x => x.Id == 5590).Select(x => x.FileData).SingleOrDefault<byte[]>();
然后我尝试实现 blob type listed here但是现在运行时我收到错误:
"Unable to cast object of type 'System.Byte[]' to type 'TestProg.DatabaseConverter.Entities.Blob'."}
我无法想象 Ole 对象大于 100mb 但无法检查。有什么好的方法可以使用 Fluent NHibernate 将其从一个数据库中复制出来并将其保存到另一个数据库中,还是我需要查看其他选项?
我处理这些的正常循环是:
IList<Entities.Access.Revision> result;
IList<int> recordIds = aSession.Query<Entities.Access.Revision>().Select(x => x.Id).ToList<int>();
foreach (int recordId in recordIds)
{
result = aSession.Query<Entities.Access.Revision>().Where(x => x.Id == recordId).ToList<Entities.Access.Revision>();
Save(sqlDb, result);
}
保存功能只是将属性从一个实体复制到另一个实体,对于某些实体,它用于操作数据或向用户提供与数据问题相关的反馈。我正在为两个数据库使用无状态 session 。
--
从进一步测试来看,它似乎卡在上面的物体大约有 60-70mb。我目前正在测试使用 GetBytes 使用 OleDbDataReader 抓取数据。
--
更新(11 月 24 日):我还没有找到使它与 NHibernate 一起工作的方法。我确实使用了常规的 db 命令对象。我已经将我制作的功能代码放在下面,供任何好奇的人找到。这是来 self 的数据库转换器的代码,因此前缀为“a”的对象是访问数据库对象,“s”是 sql 对象。
public void MigrateBinaryField(int id, string tableName, string fieldName)
{
var aCmd = new OleDbCommand(String.Format(@"SELECT ID, {0} FROM {1} WHERE ID = {2}", fieldName, tableName, id), aConn);
using (var reader = aCmd.ExecuteReader(System.Data.CommandBehavior.SequentialAccess))
{
while (reader.Read())
{
if (reader[fieldName] == DBNull.Value)
return;
long read = 0;
long offset = 0;
// Can't .WRITE a NULL column so need to set an initial value
var sCmd = new SqlCommand(string.Format(@"UPDATE {0} SET {1} = @data WHERE OldId = @OldId", tableName, fieldName), sConn);
sCmd.Parameters.AddWithValue("@data", new byte[0]);
sCmd.Parameters.AddWithValue("@OldId", id);
sCmd.ExecuteNonQuery();
// Incrementally store binary field to avoid OutOfMemoryException from having entire field loaded in memory
sCmd = new SqlCommand(string.Format(@"UPDATE {0} SET {1}.WRITE(@data, @offset, @len) WHERE OldId = @OldId", tableName, fieldName), sConn);
while ((read = reader.GetBytes(reader.GetOrdinal(fieldName), offset, buffer, 0, buffer.Length)) > 0)
{
sCmd.Parameters.Clear();
sCmd.Parameters.AddWithValue("@data", buffer);
sCmd.Parameters.AddWithValue("@offset", offset);
sCmd.Parameters.AddWithValue("@len", read);
sCmd.Parameters.AddWithValue("@OldId", id);
sCmd.ExecuteNonQuery();
offset += read;
}
}
}
}
最佳答案
这听起来像是我在其他框架之上使用 .NET 时看到的结果。
NHibernate 下 ADO.NET 下的 native 数据库驱动程序(此处有意使用两个“下部”)将需要一个固定的目标内存块,当驱动程序填充它时,该内存块不能在内存中移动。由于 .NET 垃圾收集器可以在单独的线程上随机移动内存块以压缩堆,NHibernate 的底层 .NET 数据库层必须创建一个非托管内存块来接收数据,这有效地使内存量翻倍需要加载记录。
此外,我还没有验证下一点,但 NHibernate 应该尝试缓存记录 block ,因为它绕过了一些关系数据库查询操作。这允许 NHibernate 发出更少的数据库请求,这对于较小的记录大小是最佳的,但一次需要许多记录(包括许多 blob)以适应内存。
作为解决问题的第一步,确保该进程确实使机器内存不足(或者如果它是 32 位,确保它达到 2GB 限制)。如果是这样,尝试确定基线——如果它正在处理具有各种 blob 大小的记录,它使用的最小和最大内存是多少?由此,您可以估计该大记录(或包含该记录的缓存 block !)需要多少内存。
64 位和更多物理内存可能是一种强力解决方案,如果您还没有运行 64 位,并且甚至可以选择更大的硬件。
另一种可能的解决方案是检查 NHibernate 是否具有关于它如何缓存数据的可配置设置或属性。例如,检查您是否可以设置一个属性来限制一次加载多少条记录,或者告诉它以字节为单位将其缓存限制为特定大小。
一个更有效的解决方案是将 ADO.NET 代码用于 blob;这可能是最好的解决方案,特别是如果您希望得到比这个特定的 60-70MB blob 更大的 blob。 MS Access 通常会允许多个只读连接,所以只要 NHibernate 没有将数据库设置为阻止其他连接,这应该就可以工作。
关于c# - NHibernate OutOfMemoryException 查询大字节 [],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33392921/
我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.
我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
我正在尝试查询我的Rails数据库(Postgres)中的购买表,我想查询时间范围。例如,我想知道在所有日期的下午2点到3点之间进行了多少次购买。此表中有一个created_at列,但我不知道如何在不搜索特定日期的情况下完成此操作。我试过:Purchases.where("created_atBETWEEN?and?",Time.now-1.hour,Time.now)但这最终只会搜索今天与那些时间的日期。 最佳答案 您需要使用PostgreSQL'sdate_part/extractfunction从created_at中提取小时
我在Rails上使用带有ruby的solr。一切正常,我只需要知道是否有任何现有代码来清理用户输入,比如以?开头的查询。或* 最佳答案 我不知道执行此操作的任何代码,但理论上可以通过查看parsingcodeinLucene来完成并搜索thrownewParseException(只有16个匹配!)。在实践中,我认为您最好只捕获代码中的任何solr异常并显示“无效查询”消息或类似信息。编辑:这里有几个“sanitizer”:http://pivotallabs.com/users/zach/blog/articles/937-s
我正在为锦标赛开发一个Rails应用程序。我在这个查询中使用了三个模型:classPlayertruehas_and_belongs_to_many:tournamentsclassTournament:destroyclassPlayerMatch"Player",:foreign_key=>"player_one"belongs_to:player_two,:class_name=>"Player",:foreign_key=>"player_two"在tournaments_controller的显示操作中,我调用以下查询:Tournament.where(:id=>params
我想用sunspot重现以下原始solr查询q=exact_term_text:fooORterm_textv:foo*ORalternate_text:bar*但我无法通过标准的太阳黑子界面理解这是否可能以及如何实现,因为看起来:fulltext方法似乎不接受多个文本/搜索字段参数我不知道将什么参数作为第一个参数传递给fulltext,就好像我通过了"foo"或"bar"结果不匹配如果我传递一个空参数,我得到一个q=*:*范围过滤器(例如with(:term).starting_with('foo*')(顾名思义)作为过滤器查询应用,因此不参与评分。似乎可以手动编写字符串(或者可能使
例如,假设我有一个名为Products的模型,并且在ProductsController中,我有以下代码用于product_listView以显示已排序的产品。@products=Product.order(params[:order_by])让我们想象一下,在product_listView中,用户可以使用下拉菜单按价格、评级、重量等进行排序。数据库中的产品不会经常更改。我很难理解的是,每次用户选择新的order_by过滤器时,rails是否必须查询,或者rails是否能够以某种方式缓存事件记录以在服务器端重新排序?有没有一种方法可以编写它,以便在用户排序时rails不会重新查询结果