Linq to Entity 是一个非常棒的工具。
但是如果“滥用”就会发生奇怪的问题。
最近的项目中,遇到如下境况:
有300个表结构一致的表(拗口),需要逐一读取300个表的一个数据,排序,然后取出最小的那个数(假设这个数属于表TableA),然后从TableA中再取一个数,排序.......
然后我用Samphore,大致代码如下:
class QHelper
{
public QHelper(IEnumerable<TickData> arg_Q,string arg_strSelectQuery , MarketContext arg_MarketContext)
{
SelectQueryString = arg_strSelectQuery;
Q = arg_Q;
MarketContext = arg_MarketContext;
_task = new Task(() =>
{
foreach (var data in Q)
{
norlib.DebugHelper.DebugHelper.Set(arg_strSelectQuery , "wait data");
_sph.WaitOne();
norlib.DebugHelper.DebugHelper.Set(arg_strSelectQuery, "got data");
_data = data;
}
IsCompleted = true;
});
_task.Start();
}
public IEnumerable<TickData> Q { get; private set; }
public TickData Data
{
get
{
lock (_lockGetData)
{
if (IsCompleted)
return null;
_sph.Release();
while (true)
{
if (IsCompleted)
return null;
if (_data != null)
{
var ret = _data;
_data = null;
return ret;
}
Thread.Sleep(100);
}
}
}
}
public string SelectQueryString { get; set; }
public bool IsCompleted { get; private set; }
Task _task;
TickData _data;
Semaphore _sph = new Semaphore(0, 1);
MarketContext MarketContext;
object _lockGetData = new object();
}
用户只需要不断读取Data,直到返回null就可以了。
Query也对用户隐藏了。
写完感觉良好。
跑起来后就发现问题有2个。
1.300个表速度很慢,就是Data 获取的很慢
2. 在跑了一段时间后,会出现2种错误:1.远程连接被关闭 2. EndOfStreamException
个人认为这都是因为Query长时间处于非工作状态,导致mysql关闭连接所致。(Entity to SQL使用 连接池)
最后只得牺牲空间,Query中去掉等待,直接加入Queue
解决了速度问题和错误的问题,当然内存的损耗也很惊人。(⊙_⊙)