使用linq生成直接更新而不选择

时间:2009-01-14 22:56:53

标签: c# .net sql linq

G'day大家。

我还在学习LINQ,如果这是天真的话请原谅我。当您直接处理SQL时,可以使用条件生成更新命令,而无需运行select语句。

当我使用linq时,我似乎遵循以下模式:

  1. 选择实体
  2. 修改实体
  3. 提交更改
  4. 我想要做的是使用linq和延迟执行的直接更新。是否有可能直接在SQL上执行实际执行而没有任何数据传输到客户端?

    DataContext dc = new DataContext
    
    var q = from product in dc.Products
            where product.Type = 1
            set product.Count = 0
    
    dc.SubmitChanges
    

    因此,实质上LINQ具有所需的所有信息,而无需使用select来生成更新命令。它将运行SQL:

    Update Products Set Count = 0 Where Type = 1
    

    LINQ中是否存在类似“set”的关键字?

7 个答案:

答案 0 :(得分:45)

您实际上可以让LINQ-to-SQL生成更新语句:

Foo foo=new Foo { FooId=fooId }; // create obj and set keys
context.Foos.Attach(foo);
foo.Name="test";
context.SubmitChanges();

在您的Dbml中为所有属性设置UpdateCheck =“Never”。

这将生成单个更新语句,而无需先执行选择。

一个警告:如果您希望能够将Name设置为null,则必须将foo对象初始化为其他值,以便Linq可以检测到更改:

Foo foo=new Foo { FooId=fooId, Name="###" };
...
foo.Name=null;

如果您想在更新时检查时间戳,也可以这样做:

Foo foo=new Foo { FooId=fooId, Modified=... }; 
// Modified needs to be set to UpdateCheck="Always" in the dbml

答案 1 :(得分:29)

不,LINQ和LINQ to SQL都没有基于集合的更新功能。

在LINQ to SQL中,您必须查询要更新的对象,根据需要更新字段/属性,然后调用SubmitChanges()。例如:

var qry = from product in dc.Products where Product.Name=='Foobar' select product;
var item = qry.Single();
item.Count = 0;
dc.SubmitChanges();

如果您想进行批处理:

var qry = from product in dc.Products where Product.Type==1 select product;
foreach(var item in qry)
{
  item.Count = 0;
}
dc.SubmitChanges();

或者,您可以自己编写查询:

dc.ExecuteCommand("update Product set Count=0 where Type=1", null);

答案 2 :(得分:3)

Linq 2 SQL没有SQL的直接插入/更新/删除等价物。在V1中,您可以使用linq进行的唯一更新被认为是上下文中的SubmmitChanges,或者如果您回退到sql。

然而,有些人试图使用自定义实现来克服linq的这种限制。

Linq batch update.

答案 3 :(得分:3)

PLINQO(http://plinqo.com)框架正在使用LINQ批量更新来执行更新

context.Task.Update(t => t.Id == 1, t2 => new Task {StatusId = 2});

这将执行Update Task Set StatusId = 2 Where Id = 1

答案 4 :(得分:0)

使用此扩展方法:EntityExtensionMethods.cs

public static void UpdateOnSubmit<TEntity>(this Table<TEntity> table, TEntity entity, TEntity original = null)
    where TEntity : class, new()
{
    if (original == null)
    {
        // Create original object with only primary keys set
        original = new TEntity();
        var entityType = typeof(TEntity);
        var dataMembers = table.Context.Mapping.GetMetaType(entityType).DataMembers;
        foreach (var member in dataMembers.Where(m => m.IsPrimaryKey))
        {
            var propValue = entityType.GetProperty(member.Name).GetValue(entity, null);
            entityType.InvokeMember(member.Name, BindingFlags.SetProperty, Type.DefaultBinder,
                original, new[] { propValue });
        }
    }

    // This will update all columns that are not set in 'original' object. For
    // this to work, entity has to have UpdateCheck=Never for all properties except
    // for primary keys. This will update the record without querying it first.
    table.Attach(entity, original);
}

要使用它,请确保传递给entity方法的UpdateOnSubmit对象具有为要更新的记录设置的所有主键属性。然后,此方法将使用entity对象中的其余属性更新记录,而不首先拉取记录。

致电UpdateOnSubmit后,请务必致电SubmitChanges()申请更改。

答案 5 :(得分:0)

您可以使用Entity Framework Extensions库,它支持批量更新和批量合并,但库不是免费的:

  

PM&gt;安装包Z.EntityFramework.Extensions

using Z.EntityFramework.Plus;

...

dc.Products
    .Where(q => q.Type == 1)
    .Update(q => new Product { Count = 0 });

答案 6 :(得分:-2)

试试这个:

dbEntities.tblSearchItems
     .Where(t => t.SearchItemId == SearchItemId)
     .ToList()
     .ForEach(t => t.isNew = false);
dbEntities.SaveChanges();