C# 连接期间LINQ行内属性更新
这次讨论我有两个目标,A和B。我可以通过公共关系或外键连接这些对象(表)。我正在使用linq进行连接,我只想在结果集中返回ObjectA;但是,我希望在连接期间使用ObjectB中的数据更新ObejctA的属性,以便从LINQ查询中获得的ObjectAs与所选存储介质中的原始状态“略有”不同 这是我的查询,您可以看到,我只希望能够执行类似objectA.SomeProperty=objectB.AvalueIwant的操作 我知道我可以在我的select和spin-up新OBjectAs中做一个新的操作,但是如果可能的话,我希望避免这样做,而只是更新一个字段C# 连接期间LINQ行内属性更新,c#,linq,C#,Linq,这次讨论我有两个目标,A和B。我可以通过公共关系或外键连接这些对象(表)。我正在使用linq进行连接,我只想在结果集中返回ObjectA;但是,我希望在连接期间使用ObjectB中的数据更新ObejctA的属性,以便从LINQ查询中获得的ObjectAs与所选存储介质中的原始状态“略有”不同 这是我的查询,您可以看到,我只希望能够执行类似objectA.SomeProperty=objectB.AvalueIwant的操作 我知道我可以在我的select和spin-up新OBjectAs中做一个
return from objectA in GetObjectAs()
join objectB in GetObjectBs()
on objectA.Id equals objectB.AId
// update object A with object B data before selecting it
select objectA;
你能试试let语句吗?(不是在我的开发机器上亲自测试): 从单词“tables”中,听起来像是从数据库中获取这些数据。在这种情况下;不,你不能这样做。您可以做的最接近的操作是选择对象和额外的列,然后更新属性:
var qry = from objectA in GetObjectAs()
join objectB in GetObjectBs()
on objectA.Id equals objectB.AId
select new { A = objectA,
objectB.SomeProp, objectB.SomeOtherProp };
foreach(var item in qry) {
item.A.SomeProp = item.SomeProp;
item.A.SomeOtherProp = item.SomeOtherProp;
// perhaps "yield return item.A;" here
}
如果您正在对对象执行LINQ,那么可能有一些黑客的方法可以使用流畅的API来实现—尽管不太漂亮。(类似编辑)将更新方法添加到ClassA中
class ClassA {
public ClassA UpdateWithB(ClassB objectB) {
// Do the update
return this;
}
}
然后使用
return from objectA in GetObjectAs()
join objectB in GetObjectBs()
on objectA.Id equals objectB.AId
// update object A with object B data before selecting it
select objectA.UpdateWithB(objectB);
编辑:
或者使用本地lambda函数,如:
Func<ClassA, ClassB, ClassA> f = ((a,b)=> { a.DoSomethingWithB(b); return a;});
return from objectA in GetObjectAs()
join objectB in GetObjectBs()
on objectA.Id equals objectB.AId
select f(objectA , objectA );
Func f=((a,b)=>{a.DoSomethingWithB(b);返回a;});
从GetObjectAs()中的objectA返回
在GetObjectBs()中加入objectB
在objectA.Id上等于objectB.AId
选择f(objectA,objectA);
首先通过创建一个名为LinqExtensions的类来扩展Linq,使其具有Each选项
public static class LinqExtensions
{
public static void Each<T>(this IEnumerable<T> source, Action<T> method)
{
foreach (var item in source)
{
method(item);
}
}
}
参数传递示例:
objectA.Join(objectB,a=>a.Id,b=>b.Id,(a,b) => new {a,b.AValueIWant}).Each(o=>o.a.SomeMethod(o.AValueIWant));
这样做的好处是ObjectA和ObjectB不必是相同的类型。我用一个对象列表连接到一个字典(比如查找)来实现这一点。糟糕的是不清楚到底发生了什么。您最好跳过每个扩展,这样写
foreach(var change in objectA.Join(objectB,a=>a.Id,b=>b.Id,(a,b) => new {a,b.AValueIWant}))
{
change.a.SomeProperty = change.AValueIWant;
change.a.SomeMethod(change.AValueIWant);
}
但为了更清楚,我可能会这样做:
foreach(var update in objectA.Join(objectB,objectA=>objectA.Id,objectB=>objectB.Id,(objectA,objectB) => new {objectA, Value = objectB.AValueIWant}))
{
update.objectA.SomeProperty = update.Value;
}
您将需要在新对象中返回整个ObjectA,因为它将是只读的,并且唯一有效的原因是集合中的对象被引用,允许您对对象的属性进行更改
但最终,最明显的做法是跳过LINQ连接,在集合中循环查找匹配项,这将有助于将来的维护。LINQ非常棒,但就像当你有锤子的时候,它不会让一切都像钉子一样,当你有一个集合的时候,它并不意味着LINQ就是答案。我在这里做一个左连接,所以我仍然拥有objectA的所有数据,即使objectB中的相应属性为空。因此,如果objectB中的相应属性为null,则必须定义在objectA中执行的操作。我一直使用这个语句连接两组数据。您不需要详尽地列出objectA中的所有属性及其映射方式,只需要列出要使用objectB更新的值。除非定义了到objectB的映射,否则objectA中预先存在的值是安全的
return from objectA in GetObjectAs()
join objectB in GetObjectBs()
on objectA.Id equals objectB.AId into combinedObj
from subObject in combinedObj.DefaultIfEmpty()
// update object A with object B data before selecting it
select ((Func<objectAType>)(() =>
{
objectA.property = ((subObject == null) ? "Object B was null" : subObject.property);
objectA.property = ((subObject == null) ? "Object B was null" : subObject.property);
return objectA;
}))()
从GetObjectAs()中的objectA返回
在GetObjectBs()中加入objectB
在objectA.Id上等于objectB.AId到combinedObj
来自CombinedObject.DefaultIfEmpty()中的子对象
//在选择对象A之前,使用对象B数据更新对象A
选择((Func)(()=>
{
objectA.property=((子对象==null)?“对象B为null”:子对象.property);
objectA.property=((子对象==null)?“对象B为null”:子对象.property);
返回对象a;
}))()
您可以通过以下方式进行尝试:
var list1 = new List<ItemOne>
{
new ItemOne {IDItem = 1, OneProperty = "1"},
new ItemOne {IDItem = 2, OneProperty = null},
new ItemOne {IDItem = 3, OneProperty = "3"},
new ItemOne {IDItem = 4, OneProperty = "4"}
};
var list2 = new List<ItemTwo>
{
new ItemTwo {IDItem = 2, TwoProperty = "2"},
new ItemTwo {IDItem = 3, TwoProperty = "3"},
};
var query = list1.Join(list2, l1 => l1.IDItem, l2 => l2.IDItem, (l1, l2) =>
{
l1.OneProperty = l2.TwoProperty;
return l1;
});
var list1=新列表
{
新项目一{IDItem=1,OneProperty=“1”},
新项目一{IDItem=2,OneProperty=null},
新项目一{IDItem=3,OneProperty=“3”},
新项目一{IDItem=4,OneProperty=“4”}
};
var list2=新列表
{
新项目二{IDItem=2,TwoProperty=“2”},
新项目二{IDItem=3,TwoProperty=“3”},
};
var query=list1.Join(list2,l1=>l1.IDItem,l2=>l2.IDItem,(l1,l2)=>
{
l1.OneProperty=l2.TwoProperty;
返回l1;
});
不,你不能那样做;让我们只创建新变量-它不进行赋值。我正在从数据库中提取,但我不想将这些更改发布回数据库,只是允许这个“新”对象a携带一些不同的数据。这不适用于linq to sql,因为我有一个属性,该属性具有[notmap]
属性
return from objectA in GetObjectAs()
join objectB in GetObjectBs()
on objectA.Id equals objectB.AId into combinedObj
from subObject in combinedObj.DefaultIfEmpty()
// update object A with object B data before selecting it
select ((Func<objectAType>)(() =>
{
objectA.property = ((subObject == null) ? "Object B was null" : subObject.property);
objectA.property = ((subObject == null) ? "Object B was null" : subObject.property);
return objectA;
}))()
var list1 = new List<ItemOne>
{
new ItemOne {IDItem = 1, OneProperty = "1"},
new ItemOne {IDItem = 2, OneProperty = null},
new ItemOne {IDItem = 3, OneProperty = "3"},
new ItemOne {IDItem = 4, OneProperty = "4"}
};
var list2 = new List<ItemTwo>
{
new ItemTwo {IDItem = 2, TwoProperty = "2"},
new ItemTwo {IDItem = 3, TwoProperty = "3"},
};
var query = list1.Join(list2, l1 => l1.IDItem, l2 => l2.IDItem, (l1, l2) =>
{
l1.OneProperty = l2.TwoProperty;
return l1;
});