我问了这个问题,How do I return one-to-many records in a specific order with Dapper and multi-mapping?
答案很好,但我不明白为什么会这样。我不明白,因为我不知道如何阅读它。
如何将其重写为代表?我想看看函数而不是lambda,只是因此我可以想象它。
var groupedPosts = userposts.GroupBy(f => f.UserId, posts => posts, (k, v) =>
new User()
{
UserId = k,
Name = v.FirstOrDefault().Name,
Posts = v.Select(f => new Post() { Id = f.Id,
Title= f.Title,
Content = f.Content})
}).ToList();
我最感兴趣的是这部分:
f => f.UserId, posts => posts,
及其与
的关系(k, v)
之后,我相信,我可以得到它。
答案 0 :(得分:2)
你的意思是你想要看到这样的东西:
public static int fId(Foo f)
{
return f.Id;
}
public static Foo fPosts(Foo f)
{
return f;
}
public static User fSelect(int k, IEnumerable<Foo> v )
{
return new User()
{
UserId = k,
Name = v.FirstOrDefault().Name,
Posts = v.Select(f => new Post()
{
Id = f.Id,
Title = f.Title,
Content = f.Content
})
};
}
var groupedPosts = userposts.GroupBy(fId, fPosts, fSelect);
重要的是:fId返回int
。并且fPosts返回Foo
。因此,fSelect的参数为int
和IEnumerable<Foo>
。
答案 1 :(得分:2)
GroupBy是一种扩展方法,有多个重载here。 您的示例使用的重载具有以下读数。
第一个参数(f => f.UserId
)是一个所谓的密钥选择器 - 这将确定每个组的密钥。
第二个参数(posts => posts
)是值选择器 - 这将确定组中包含的值的类型
调用第三个参数((k, v)
),结果选择器会在实现组之前为您提供一个额外的步骤。您可以访问键(UserId
)作为第一个参数和集合值(将包含在组中的值 - 所有{{1}对于Posts
),这使您能够更改/过滤/预测结果。
因此,例如,如果第三个参数被省略,那么结果将是组,其中键是UserId
,组中的值是UserId
,但是我们现在可以使用第三个参数访问UserId(密钥)和帖子(值)并将它们投影到新类型 - Posts
。
答案 2 :(得分:1)
阅读你的答案:
按UserId分组用户点;对于每个组,请获取该ID的所有帖子;现在,对于每个组,请使用userId及其所有帖子,并与他们一起做。
<强>解释
表达式f => f.UserId
,posts => posts
看起来好像是函数。但他们不是。嗯,他们是,但有点不......好吧,这很令人困惑。他们正在做的是填写一些C#语言中不存在的语法。
重点是,您如何与GroupBy()
方法进行沟通:
如果C#可以支持这种语法,那可能会很好:
var groupedPosts = userposts.GroupBy( UserId, this, (k, v) => {...});
但你可以立刻看到它永远无法编译。您必须向编译器解释UserId
表示该名称的UserPost
的属性,并且this
依次限定每个用户邮件。在仿制药之前lambdas,.net经常通过使用字段名字符串来解决这类问题:
var groupedPosts = userposts.GroupBy( "UserId", "", (k, v) => {...});
然后必须有一些运行时反射将该字符串转换为属性名称&amp;然后得到一个值,&amp;认识到“”意味着整个UserPost
但是在C#中我们喜欢强力打字。 lambda给出了一种可爱但不是立即显而易见的方式,以强有力的方式“命名”一个属性:
f=> f.UserId
你知道吗?阅读这不是一个功能,而是命名属性:“我想要每个用户信息的UserId”
同样,您可以“命名”整个实体:
f => f // means exactly the same as posts=>posts
(函数x=>x
在计算机科学中称为身份函数)。这就是为什么很难“想象”代表。 lambda被用作一种简洁的强类型方式来识别字段或属性。
[如果这很清楚,现在让我收回'这不是一个功能'的陈述。这是一个功能。假设您要分组,而不是UserId,而是名称和,您希望分组不区分大小写。然后你可以使用:
f=> f.Name.ToUpper()
因此,作为一个功能不仅仅是一种获得强类型的方法,它还提供了更强大的选项。您也可以在SQL中执行此操作。 ]
最后一点:
(k, v) => {....}
然后你读作“为每个userId&amp;和该用户ID的帖子集,做......与他们一起”。请注意名称k&amp; v是任意参数名称,在这里没有那么有用。我可能用过:
(userid, postsforuserid) => {...}
将所有内容整合在一起,您可以阅读
userposts.GroupBy(
userpost => userpost.UserId,
userpost => userpost,
(userid, postsforuserid) => {...})
大声说:
按UserId分组用户点;对于每个组,请获取该ID的所有帖子;现在,对于每个组,请使用userId及其所有帖子并使用它们执行
-----------------------------------
所以,你看,看到代表没有多大帮助:
void Main()
{
Del k = delegate (UserPost post) { return post.UserId; };
Del v = delegate (UserPost post) { return post; };
}
class UserId { }
class UserPost { public UserId UserId { get; set; } }