Lambda 在加入时不相等
Lambda not equal on join
Table 1 个名为 Category 包含 70 条记录
Table 2 个调用的 FilterCategorys 包含 0 条记录(当前)。
我的 lambda 连接,我只想提取不匹配的记录,所以在这种情况下,我希望得到 70 条记录。这是我不正确的 Lambda:
var filteredList = categorys
.Join(filterCategorys,
x => x.Id,
y => y.CategoryId,
(x, y) => new { catgeory = x, filter = y })
.Where(xy => xy.catgeory.Id != xy.filter.CategoryId)
.Select(xy => new Category()
{
Name = xy.catgeory.Name,
Id = xy.catgeory.Id,
ParentCategoryId = xy.catgeory.ParentCategoryId
})
.ToList();
我需要的正确语法是什么?
试试这个:
var categories= ...
var filteredCategories=...
var allExceptFiltered = categories.Except(filteredCategories, new CategoryComparer()).ToList();
如果您不提供自定义比较器,框架无法知道 2 个类别对象是相同的(即使它们具有相同的 ID),它只是认为它们是不同的对象(它会检查引用相等 )
因此您必须将此 class 添加到您的项目中:
public class CategoryComparer: IEqualityComparer<Category>
{
public bool Equals(Category x, Category y)
{
if (x == null && y == null)
return true;
if (x == null)
return false;
if (y == null)
return false;
return x.CategoryId.GetHashCode() == y.CategoryId.GetHashCode();
}
public int GetHashCode(Category obj)
{
return obj.CategoryId.GetHashCode();
}
}
更新
另请查看 Wyatt Earp 的回答,了解如何进行外部连接非常有用
更新 2
您的问题是 Join 方法。
Where子句是"called"在join.so之后join.so之后你加入了基于ID的列表你select那些有不同ID的,这就是为什么你没有结果
不确定您是否需要使用 lambda(而不是查询语法),但我更喜欢具有外连接的语句的查询语法。
这应该是等价的:
var filteredList = (
from c in Categorys
join fc in FilterCategorys on c.Id equals fc.CategoryId into outer
from o in outer.DefaultIfEmpty()
select new
{
Category = new Category
{
Name = c.Name,
Id = c.Id,
ParentCategoryId = c.ParentCategoryId
},
Exists = (o != null)
})
.Where(c => !c.Exists)
.Select(c => c.Category);
如果您想在纯 lambda 中执行此操作:
var match = categorys.Join(filterCategorys, x => x.Id, y => y.CategoryId, (x, y) => new { Id = x.Id });
var filteredList = categorys.Where(x => !match.Contains(new {Id = x.Id}));
我没有测过它的性能,但是对于 70 条记录,优化不是问题。
好吧,我想出了一个解决方案,消除了加入的需要。
var currentIds = filterCategorys.Select(x => x.Id).ToList();
var filteredList = categorys.Where(x => !currentIds.Contains(x.Id));
与@Zoff Dino 的回答非常相似,不确定性能,也许有人想检查一下。
你能画括号吗,它应该可以。
....哪里(xy => (xy.catgeory.Id != xy.filter.CategoryId))
Table 1 个名为 Category 包含 70 条记录 Table 2 个调用的 FilterCategorys 包含 0 条记录(当前)。
我的 lambda 连接,我只想提取不匹配的记录,所以在这种情况下,我希望得到 70 条记录。这是我不正确的 Lambda:
var filteredList = categorys
.Join(filterCategorys,
x => x.Id,
y => y.CategoryId,
(x, y) => new { catgeory = x, filter = y })
.Where(xy => xy.catgeory.Id != xy.filter.CategoryId)
.Select(xy => new Category()
{
Name = xy.catgeory.Name,
Id = xy.catgeory.Id,
ParentCategoryId = xy.catgeory.ParentCategoryId
})
.ToList();
我需要的正确语法是什么?
试试这个:
var categories= ...
var filteredCategories=...
var allExceptFiltered = categories.Except(filteredCategories, new CategoryComparer()).ToList();
如果您不提供自定义比较器,框架无法知道 2 个类别对象是相同的(即使它们具有相同的 ID),它只是认为它们是不同的对象(它会检查引用相等 )
因此您必须将此 class 添加到您的项目中:
public class CategoryComparer: IEqualityComparer<Category>
{
public bool Equals(Category x, Category y)
{
if (x == null && y == null)
return true;
if (x == null)
return false;
if (y == null)
return false;
return x.CategoryId.GetHashCode() == y.CategoryId.GetHashCode();
}
public int GetHashCode(Category obj)
{
return obj.CategoryId.GetHashCode();
}
}
更新
另请查看 Wyatt Earp 的回答,了解如何进行外部连接非常有用
更新 2
您的问题是 Join 方法。
Where子句是"called"在join.so之后join.so之后你加入了基于ID的列表你select那些有不同ID的,这就是为什么你没有结果
不确定您是否需要使用 lambda(而不是查询语法),但我更喜欢具有外连接的语句的查询语法。
这应该是等价的:
var filteredList = (
from c in Categorys
join fc in FilterCategorys on c.Id equals fc.CategoryId into outer
from o in outer.DefaultIfEmpty()
select new
{
Category = new Category
{
Name = c.Name,
Id = c.Id,
ParentCategoryId = c.ParentCategoryId
},
Exists = (o != null)
})
.Where(c => !c.Exists)
.Select(c => c.Category);
如果您想在纯 lambda 中执行此操作:
var match = categorys.Join(filterCategorys, x => x.Id, y => y.CategoryId, (x, y) => new { Id = x.Id });
var filteredList = categorys.Where(x => !match.Contains(new {Id = x.Id}));
我没有测过它的性能,但是对于 70 条记录,优化不是问题。
好吧,我想出了一个解决方案,消除了加入的需要。
var currentIds = filterCategorys.Select(x => x.Id).ToList();
var filteredList = categorys.Where(x => !currentIds.Contains(x.Id));
与@Zoff Dino 的回答非常相似,不确定性能,也许有人想检查一下。
你能画括号吗,它应该可以。 ....哪里(xy => (xy.catgeory.Id != xy.filter.CategoryId))