Linq InsertAllOnSubmit if not exist

时间:2015-07-31 19:56:13

标签: c# linq tsql

To insert records if not exist I'm currently doing:

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();
}

I know that I can also check these Items one by one and insert non-existing ones into another list and then at the end insert all of them using InsertAllOnSubmit() but this does not solve my problem either as I'm going to check thousand of Items and I don't want to execute thouthand queries for checking these Items. Is there any way to use InsertAllOnSibmit in a way that insert only non-exsiting Items?

Edit: I have no obligation to use Linq and if somebody knows a better way to do this by stored procedures or any other way I really I appreciate if you share.

3 个答案:

答案 0 :(得分:2)

One query to figure out what needs to be inserted, then after some in-memory manipulation you can 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();
}

答案 1 :(得分:1)

You can try somthing like: note, that concurrency could be an issue this way, the only way I see this working properlly is with store procedures and blocking strategies in place, but if want to do it with 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

答案 2 :(得分:1)

不必 复杂。名称似乎是主键。只需确定要插入的项目集中的数据库中的哪些名称。然后插入它们,不包括存在的那些。

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();