从 dbset.local 或数据库获取数据的存储库模式
Repository pattern to get data from dbset.local or database
我正在编写一个方法,它将循环一些数据并在数据库中创建记录,该方法使用存储库。
原来是这样的:
///Lets assume that there is a string array called arr somewhere above this.
var repo = new ItemRepository();
for (int i = 0; i<1000; i++)
{
if (repo.MyItems.Count(x=>x.ID == arr[i]) == 0)
{
//Doesn't Exist Create
repo.MyItems.Add(new Item(arr[i]));
repo.Save();
}
else
{
//Here I will get an instance of the entity that already exists and do some updates to it
}
}
这行得通,但因为它在每次迭代时都保存到数据库中,所以速度很慢,所以我想做的是将其更改为如下所示:
var repo = new ItemRepository();
for (int i = 0; i<1000; i++)
{
if (repo.MyItems.Count(x=>x.ID == arr[i]) == 0)
{
//Doesn't Exist Create
repo.MyItems.Add(new Item(arr[i]));
}
else
{
//Here I will get an instance of the entity that already exists and do some updates to it
}
}
repo.Save();
因此只有在创建所有实体后才进行保存,因此它是一个大数据库插入而不是数千个。
问题是因为这些项目还没有被保存回我的数据库 repo.MyItems.Count(x=>x.ID == i) 没有带回任何东西(尽管实体有已添加到 dbset.Local collection.
我想我的问题是如何修改我的存储库以允许我查询本地 collection 和数据库 - 因为这是关键,它们可能存在于数据库中或者它们可能已经被添加到存储库而不是插入到数据库中。
以上是伪代码,但有点代表我在做什么,存储库方法类似于
public int count(string val)
{
IQueryable<T> data = _dbSet;
return data.Count(x=>x.COLUMNNAME == val);
}
同样,这只是我在回购协议中的代表,但它应该让我对我的目标有所了解。
希望我理解正确,这是我通常做的:
var repo = new ItemRepository();
Int32 index = 0;
Int32 localIndex = 0;
while (index < arr.Length) {
repo.MyItems.Add(new Item(arr[index]));
index++;
localIndex++;
if (localIndex == 1000) {
repo.Save();
localIndex = 0;
}
}
if (localIndex > 0) {
repo.Save();
}
如果有人感兴趣,这就是我实现的,它似乎有效,但我最终放弃了它,因为意识到这几乎允许 "Dirty Reads" 具有对系统的其余部分产生影响,我们决定多次保存的性能损失比重新处理系统的大部分内容更可取 - 或实施允许脏读的回购...
请注意,GetSingle 替换了上面伪代码中的 Count。
public T GetSingle(System.Linq.Expressions.Expression<Func<T, bool>> filter = null)
{
//Check the local collection first
IQueryable<T> localEntities = _dbset.Local.AsQueryable();
if (filter != null)
{
localEntities = localEntities.Where(filter);
}
if (localEntities.Count() > 0)
{
return localEntities.FirstOrDefault();
}
else
{
//A local version of this was not found - try the database.
IQueryable<T> query = this._dbset;
if (filter != null)
{
query = query.Where(filter);
}
return query.FirstOrDefault();
}
}
如果有更好的方法来做到这一点,我真的很想知道,因为这是一个我可能会再次遇到的问题,下次我可能需要坚持到底!
我正在编写一个方法,它将循环一些数据并在数据库中创建记录,该方法使用存储库。
原来是这样的:
///Lets assume that there is a string array called arr somewhere above this.
var repo = new ItemRepository();
for (int i = 0; i<1000; i++)
{
if (repo.MyItems.Count(x=>x.ID == arr[i]) == 0)
{
//Doesn't Exist Create
repo.MyItems.Add(new Item(arr[i]));
repo.Save();
}
else
{
//Here I will get an instance of the entity that already exists and do some updates to it
}
}
这行得通,但因为它在每次迭代时都保存到数据库中,所以速度很慢,所以我想做的是将其更改为如下所示:
var repo = new ItemRepository();
for (int i = 0; i<1000; i++)
{
if (repo.MyItems.Count(x=>x.ID == arr[i]) == 0)
{
//Doesn't Exist Create
repo.MyItems.Add(new Item(arr[i]));
}
else
{
//Here I will get an instance of the entity that already exists and do some updates to it
}
}
repo.Save();
因此只有在创建所有实体后才进行保存,因此它是一个大数据库插入而不是数千个。
问题是因为这些项目还没有被保存回我的数据库 repo.MyItems.Count(x=>x.ID == i) 没有带回任何东西(尽管实体有已添加到 dbset.Local collection.
我想我的问题是如何修改我的存储库以允许我查询本地 collection 和数据库 - 因为这是关键,它们可能存在于数据库中或者它们可能已经被添加到存储库而不是插入到数据库中。
以上是伪代码,但有点代表我在做什么,存储库方法类似于
public int count(string val)
{
IQueryable<T> data = _dbSet;
return data.Count(x=>x.COLUMNNAME == val);
}
同样,这只是我在回购协议中的代表,但它应该让我对我的目标有所了解。
希望我理解正确,这是我通常做的:
var repo = new ItemRepository();
Int32 index = 0;
Int32 localIndex = 0;
while (index < arr.Length) {
repo.MyItems.Add(new Item(arr[index]));
index++;
localIndex++;
if (localIndex == 1000) {
repo.Save();
localIndex = 0;
}
}
if (localIndex > 0) {
repo.Save();
}
如果有人感兴趣,这就是我实现的,它似乎有效,但我最终放弃了它,因为意识到这几乎允许 "Dirty Reads" 具有对系统的其余部分产生影响,我们决定多次保存的性能损失比重新处理系统的大部分内容更可取 - 或实施允许脏读的回购...
请注意,GetSingle 替换了上面伪代码中的 Count。
public T GetSingle(System.Linq.Expressions.Expression<Func<T, bool>> filter = null)
{
//Check the local collection first
IQueryable<T> localEntities = _dbset.Local.AsQueryable();
if (filter != null)
{
localEntities = localEntities.Where(filter);
}
if (localEntities.Count() > 0)
{
return localEntities.FirstOrDefault();
}
else
{
//A local version of this was not found - try the database.
IQueryable<T> query = this._dbset;
if (filter != null)
{
query = query.Where(filter);
}
return query.FirstOrDefault();
}
}
如果有更好的方法来做到这一点,我真的很想知道,因为这是一个我可能会再次遇到的问题,下次我可能需要坚持到底!