如何在 Linq 中过滤子集合
我需要使用单个 linq 查询来过滤 linq 中实体的子元素。 这可能吗?
假设我有两个相关的表。 诗句和诗句翻译。 LINQ to SQL 创建的实体是这样的,我有一个 Verse 对象,其中包含一个子对象,该子对象是 VerseTranslation 的集合。
现在,如果我有以下 linq 查询,
var res = from v in dc.Verses
where v.id = 1
select v;
我会得到 id 为 1 的 Verses 集合,每个 verse 对象包含 VerseTranslations 中的所有子对象。
我还想做的是过滤诗歌翻译的子列表。
到目前为止,我能想到的唯一方法是使用新的匿名类型或其他方式。 如下
var res= from v in dc.Verses
select new myType
{
VerseId = v.VerseId,
VText = v.Text,
VerseTranslations = (from trans in v.VerseTranslations
where languageId==trans.LanguageId
select trans
};
上面的代码可以工作,但我必须为其声明一个新类。 有没有办法以这样的方式做到这一点:子表的过滤可以合并到第一个 linq 查询中,这样就不必声明新的类。
问候, 苹果
I need to filter the child elements of an entity in linq using a single linq query. Is this possible?
Suppose I have two related tables. Verses and VerseTranslations. The entity created by LINQ to SQL is such that i have a Verse object that contains a child object that is a collection of VerseTranslation.
Now if i have the follow linq query
var res = from v in dc.Verses
where v.id = 1
select v;
I get a collection of Verses whose id is 1 and each verse object contains all the child objects from VerseTranslations.
What I also want to do is filter that child list of Verse Translations.
So far the only way i have been able to come up with is by using a new Type Anonymous or otherwise. As follows
var res= from v in dc.Verses
select new myType
{
VerseId = v.VerseId,
VText = v.Text,
VerseTranslations = (from trans in v.VerseTranslations
where languageId==trans.LanguageId
select trans
};
The above code works, but i had to declare a new class for it. Is there no way to do it in such a manner such that the filtering on the child table can be incorporated in the first linq query so that no new classes have to be declared.
Regards,
MAC
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
从技术上来说,答案是否定的。 如果您尝试返回的数据多于单个实体对象(Verse、VerseTranslation)可以容纳的数据,则需要某种对象来“投影”到其中。 但是,您可以通过使用匿名类型来显式声明
myType
:编译器将为您生成一个具有适当类型的 Verse 和 Translations 属性的类。 只要您不需要按名称引用类型(例如,从命名方法返回),您就可以将这些对象用于任何用途。 因此,虽然您在技术上没有“声明”类型,但您仍在使用根据您的规范生成的新类型。
至于使用单个 LINQ 查询,这完全取决于您想要的数据结构。 对我来说,您的原始查询似乎最有意义:将每个
Verse
与过滤后的翻译列表配对。 如果您期望每种语言只有一个翻译,则可以使用SingleOrDefault
(或FirstOrDefault
)来展平您的子查询,或者仅使用SelectMany
,例如this:如果一个诗句有多个翻译,这将为每个诗句/翻译对返回一个“行”。 我使用
DefaultIfEmpty()
作为左连接,以确保我们能够获得所有诗句,即使它们缺少翻译。Technically, the answer is no. If you're trying to return more data than a single entity object (Verse, VerseTranslation) can hold, you'll need some sort of object to "project" into. However, you can get around explicitly declaring
myType
by using an anonymous type:The compiler will generate a class with appropriately-typed Verse and Translations properties for you. You can use these objects for just about anything as long as you don't need to refer to the type by name (to return from a named method, for example). So while you're not technically "declaring" a type, you're still using a new type that will be generated per your specification.
As far as using a single LINQ query, it all depends how you want the data structured. To me it seems like your original query makes the most sense: pair each
Verse
with a filtered list of translations. If you expect only a single translation per language, you could useSingleOrDefault
(orFirstOrDefault
) to flatten your subquery, or just use aSelectMany
like this:If a Verse has multiple translations, this will return a "row" for each Verse/Translation pair. I use
DefaultIfEmpty()
as a left join to make sure we will get all Verses even if they're missing a translation.如果这来自数据库,您可以运行第一个语句。
然后使用Where 子句加载或包含VerseTranslations。
http://msdn.microsoft.com/en-us/library/bb896249。 aspx
您的模型中 Verse 和 VerseTranslations 之间是否存在关系。 在这种情况下,这可能有效:
If this is coming from a database, you could run your first statement.
Then do a Load or Include of VerseTranslations with a Where clause.
http://msdn.microsoft.com/en-us/library/bb896249.aspx
Do you have a relationship in your model between Verse and VerseTranslations. In that case this might work:
感谢 Shiraz 的指点,我终于成功了。
这不需要投影或使用新的扩展类。
感谢所有提供意见的人。
So i finally got it to work thanks to the pointers given by Shiraz.
This does not require projection or using new extension classes.
Thanks for all your input people.
过滤对象的封闭集合
通过使用 HookedOnLinq 中的扩展方法“Update”
Filtering on the enclosed collection of the object,
By using extension method "Update" from HookedOnLinq