Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Linq InsertAllOnSubmit(如果不存在)_C#_Linq_Tsql - Fatal编程技术网

C# Linq InsertAllOnSubmit(如果不存在)

C# Linq InsertAllOnSubmit(如果不存在),c#,linq,tsql,C#,Linq,Tsql,要插入不存在的记录,请执行以下操作: using(MyDataContext db = new MyDataContext()) { for(int i=0 i<Items.Length;i++) { if(!db.Items.Any(item=> item.name == Items[i].name) db.Items.InsertOnSubmit(Items[i]); } db.SubmitChanges()

要插入不存在的记录,请执行以下操作:

using(MyDataContext db = new MyDataContext())
{
    for(int i=0 i<Items.Length;i++)
    {
        if(!db.Items.Any(item=> item.name == Items[i].name)
            db.Items.InsertOnSubmit(Items[i]);
    }
    db.SubmitChanges();
}
使用(MyDataContext db=newmydatacontext())
{
对于(int i=0 i item.name==Items[i].name)
db.Items.InsertOnSubmit(项目[i]);
}
db.SubmitChanges();
}
我知道我也可以逐个检查这些项目,将不存在的项目插入另一个列表,然后在最后使用
InsertAllOnSubmit()
插入所有项目,但这也不能解决我的问题,因为我要检查数千个项目,我不想执行用于检查这些项目的权限和查询。是否有任何方法可以使用InsertAllOnSibmit,只插入不存在的项


编辑:我没有义务使用Linq,如果有人知道通过存储过程或任何其他方式来实现这一点的更好方法,我真的非常感谢您的分享。

一个查询来确定需要插入的内容,然后在一些内存操作之后,您可以
InsertAllOnSubmit

using(MyDataContext db = new MyDataContext())
{
    var itemNames = Items.Select(i=>i.name).ToList();
    var itemNamesInDb = db.Items.Where(i=>itemNames.Contains(i.Name)).Select(i=>i.Name).ToList();
    var itemNamesNotInDb = new HashSet<string>(itemNames.Except(itemNamesInDb));
    var itemsNotInDb = Items.Where(i=>itemNamesNotInDb.Contains(i.name)).ToList();

    db.Items.InsertAllOnSubmit(itemsNotInDb);
    db.SubmitChanges();
}
使用(MyDataContext db=newmydatacontext())
{
var itemNames=Items.Select(i=>i.name.ToList();
var itemNamesInDb=db.Items.Where(i=>itemNames.Contains(i.Name)).Select(i=>i.Name.ToList();
var itemNamesNotInDb=新哈希集(itemNames.Except(itemNamesInDb));
var itemsNotInDb=Items.Where(i=>itemNamesNotInDb.Contains(i.name)).ToList();
db.Items.InsertAllOnSubmit(itemsNotInDb);
db.SubmitChanges();
}
您可以尝试以下操作: 注意,通过这种方式并发性可能是一个问题,我认为它正常工作的唯一方式是使用存储过程和阻塞策略,但是如果希望使用L2SQL来实现它

//1st db hit, to get the existing records, existing count never superior to toInsert count, 
//so it should not comsume a lot of memory
var existing = db.Items.Where(p => toInsert.Contains(p.Name)).ToList();

foreach (var input in toInsert)
{
    //fast in memory lookup
    if (existing.FirstOrDefault(p => p.Name== input) == null)
    {
       //insert the element
    }
}

//2nd db hit - submit to DB
不必那么复杂。这些名称似乎是主键。只需找出数据库中要插入的项集中的名称。然后插入它们,不包括已存在的

var excludedNames = new HashSet<string>(
    from i in db.Items
    where Items.Select(item => item.Name).Contains(i.Name)
    select i.Name
);
db.Items.InsertAllOnSubmit(
    from i in Items
    where !excludedNames.Contains(i.Name)
    select i
);
db.SubmitChanges();
var excludedNames=新哈希集(
从i到db.Items
where Items.Select(item=>item.Name).Contains(i.Name)
选择i.名称
);
db.Items.InsertAllOnSubmit(
从i到项目
其中!excludedNames.Contains(i.Name)
选择i
);
db.SubmitChanges();

i=>itemNames.Contains(i)
奇怪的谓词。更糟糕的是,如果db有500万个项将它们全部选择到内存中,以执行where方法来获取itemNamesInDb。如果我正确解释了您的反对意见,@vitalygolub,where不会在本地内存中执行;它将由EF转换为生成的sql中的WHERE…IN子句,在数据库服务器上执行。如果“我的表”中有大量记录,会影响解决方案的性能吗?在数据库中有许多记录。项不应过多地惩罚查询,尤其是在名称上有索引的情况下。但是您应该知道,items集合中可以处理的项目数量是有限制的(EF限制)。如果遇到该限制,则需要拆分这些查询(创建一个单独的函数,在给定DbContext和项列表的情况下,获取itemsNotInDb;拆分原始项列表,在每个子列表上调用该函数,并在InsertAllOnSubmit之前合并结果).您能告诉我如何使用存储过程吗?没有义务使用linq。如果您有更好的建议,请使用存储过程。我真的很感激。我可以,但这超出了问题的范围,因为您可以将其标记为linq,使用SQL或Transact-SQL重新标记,然后您可以使用存储过程将专家带到这里。=)我编辑了我的问题,但它不完全在范围内;)按原样,您正在对要插入的每个项目执行查询<代码>现有的是一个
IQueryable
。你至少要把它转换成一个列表。