与LINQ和亚音速对象映射 [英] Object mapping with LINQ and SubSonic

查看:236
本文介绍了与LINQ和亚音速对象映射的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要建亚音速3.0.0.3 ActiveRecord的一个小项目,我遇到一个问题,我似乎无法让过去。

I'm building a small project with SubSonic 3.0.0.3 ActiveRecord and I'm running into an issue I can't seem to get past.

下面是LINQ查询:

var result = from r in Release.All()
             let i = Install.All().Count(x => x.ReleaseId == r.Id)
             where r.ProductId == productId
             select new ReleaseInfo
             {
                 NumberOfInstalls = i,
                 Release = new Release
                 {
                     Id = r.Id,
                     ProductId = r.ProductId,
                     ReleaseNumber = r.ReleaseNumber,
                     RevisionNumber = r.RevisionNumber,
                     ReleaseDate = r.ReleaseDate,
                     ReleasedBy = r.ReleasedBy
                 }
             };



ReleaseInfo对象是一个自定义类,看起来像这样:

The ReleaseInfo object is a custom class and looks like this:

public class ReleaseInfo
{
    public Release Release { get; set; }
    public int NumberOfInstalls { get; set; }
}



发布并安装由亚音速生成的类。

Release and Install are classes generated by SubSonic.

当我这样做的结果看,发行属性为null。

When I do a watch on result, the Release property is null.

如果我有这样的一个简单的查询和观看结果,值不为null。

If I make this a simpler query and watch result, the value is not null.

var result = from r in Release.All()
             let i = Install.All().Count(x => x.ReleaseId == r.Id)
             where r.ProductId == productId
             select new Release
             {
                 Id = r.Id,
                 ProductId = r.ProductId,
                 ReleaseNumber = r.ReleaseNumber,
                 RevisionNumber = r.RevisionNumber,
                 ReleaseDate = r.ReleaseDate,
                 ReleasedBy = r.ReleasedBy
             };

这是我的LINQ查询问题或亚音速的限制?

Is this an issue with my LINQ query or a limitation of SubSonic?

推荐答案

我想我已经找到了答案实际这个问题。我一直在四处翻找在亚音速源,发现有两种类型的对象投影所映射的DataReader对象时:一个用于匿名类型和集团,一个是一切:

I think I've found the actual answer to this problem. I've been rummaging around in the SubSonic source and found that there are two types of object projection that are used when mapping the datareader to objects: one for anonymous types and groupings and one for everything else:

下面是一个片段:行269 - 298 SubSonic.Linq.Structure.DbQueryProvider

Here is a snippet: Line 269 - 298 of SubSonic.Linq.Structure.DbQueryProvider

IEnumerable<T> result;
Type type = typeof (T);
//this is so hacky - the issue is that the Projector below uses Expression.Convert, which is a bottleneck
//it's about 10x slower than our ToEnumerable. Our ToEnumerable, however, stumbles on Anon types and groupings
//since it doesn't know how to instantiate them (I tried - not smart enough). So we do some trickery here.
    if (type.Name.Contains("AnonymousType") || type.Name.StartsWith("Grouping`") || type.FullName.StartsWith("System.")) {
    var reader = _provider.ExecuteReader(cmd);
    result = Project(reader, query.Projector);
    } else
    {
        using (var reader = _provider.ExecuteReader(cmd))
        {
            //use our reader stuff
            //thanks to Pascal LaCroix for the help here...
            var resultType = typeof (T);
            if (resultType.IsValueType)
            {
                result = reader.ToEnumerableValueType<T>();
            }
            else
            {
                result = reader.ToEnumerable<T>();
            }
        }
    }
    return result;



原来,亚音速ToEnumerable试图在对象中的DataReader列名称匹配的属性你要投射到。从我的LINQ SQL查询看起来是这样的:

Turns out that the SubSonic ToEnumerable tries to match the column names in the datareader to the properties in the object you're trying to project to. The SQL Query from my Linq looks like this:

SELECT [t0].[Id], [t0].[ProductId], [t0].[ReleaseDate], [t0].[ReleasedBy], [t0].[ReleaseNumber], [t0].[RevisionNumber], [t0].[c0]
FROM (
  SELECT [t1].[Id], [t1].[ProductId], [t1].[ReleaseDate], [t1].[ReleasedBy], [t1].[ReleaseNumber], [t1].[RevisionNumber], (
    SELECT COUNT(*)
    FROM [dbo].[Install] AS t2
    WHERE ([t2].[ReleaseId] = [t1].[Id])
    ) AS c0
  FROM [dbo].[Release] AS t1
  ) AS t0
WHERE ([t0].[ProductId] = 2)

注意[T0]。[C0]是不一样的我的属性名称NumberOfInstalls。所以C0的价值永远不会被投射到我的对象

Notice the [t0].[c0] is not the same as my property name NumberOfInstalls. So the value of c0 never gets projected into my object.

此修复程序:
你可以简单地取出if语句,并使用慢10倍投影和一切会工作。

THE FIX: You can simply take out the if statement and use the 10x slower projection and everything will work.

这篇关于与LINQ和亚音速对象映射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆