Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用LINQ和亚音速的对象映射_C#_Linq_Subsonic_Subsonic3 - Fatal编程技术网

C# 使用LINQ和亚音速的对象映射

C# 使用LINQ和亚音速的对象映射,c#,linq,subsonic,subsonic3,C#,Linq,Subsonic,Subsonic3,我正在用亚音速3.0.0.3ActiveRecord构建一个小项目,我遇到了一个似乎无法解决的问题 以下是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

我正在用亚音速3.0.0.3ActiveRecord构建一个小项目,我遇到了一个似乎无法解决的问题

以下是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对象是一个自定义类,如下所示:

public class ReleaseInfo
{
    public Release Release { get; set; }
    public int NumberOfInstalls { get; set; }
}
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)
释放和安装是由亚音速生成的类

当我查看结果时,Release属性为null

如果我使其成为一个更简单的查询和监视结果,那么该值不为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查询的问题还是亚音速的限制?

我认为问题可能在于您实际上是在复制ORM的功能。要理解的关键是这一行:

from r in Release.All()
此行返回数据库中每个项目的完全填充的发布记录列表。在您的查询中,不需要在任何其他地方更新版本-只需返回亚音速已经为您填充的版本

使用此逻辑,您应该能够执行以下操作:

 var result = from r in Release.All()
              select new ReleaseInfo {
                  Release = r,
                  NumberOfInstalls = Install.All().Count(x => x.ReleaseId == r.Id)
              };
话虽如此,您应该查看Install.All()调用,因为这可能会非常低效。这样做的目的是从数据库中提取每个安装,将这些安装添加到对象中,然后比较.NET中每个记录的id,检查记录是否满足该条件。您可以使用亚音速中的.Find方法仅返回数据库层的某些记录,这将显著提高性能。即使如此,充气对象仍然很贵,你可能想考虑一下这里的视图或存储过程。但作为一个简单的第一步,以下步骤应该有效:

var result = from r in Release.All()
             select new ReleaseInfo {
                 Release = r,
                 NumberOfInstalls = Install.Find(x => x.ReleaseId == r.Id).Count()
             };

我认为问题可能在于您实际上是在复制ORM的功能。要理解的关键是这一行:

from r in Release.All()
此行返回数据库中每个项目的完全填充的发布记录列表。在您的查询中,不需要在任何其他地方更新版本-只需返回亚音速已经为您填充的版本

使用此逻辑,您应该能够执行以下操作:

 var result = from r in Release.All()
              select new ReleaseInfo {
                  Release = r,
                  NumberOfInstalls = Install.All().Count(x => x.ReleaseId == r.Id)
              };
话虽如此,您应该查看Install.All()调用,因为这可能会非常低效。这样做的目的是从数据库中提取每个安装,将这些安装添加到对象中,然后比较.NET中每个记录的id,检查记录是否满足该条件。您可以使用亚音速中的.Find方法仅返回数据库层的某些记录,这将显著提高性能。即使如此,充气对象仍然很贵,你可能想考虑一下这里的视图或存储过程。但作为一个简单的第一步,以下步骤应该有效:

var result = from r in Release.All()
             select new ReleaseInfo {
                 Release = r,
                 NumberOfInstalls = Install.Find(x => x.ReleaseId == r.Id).Count()
             };

我们有一个预测错误,在某些情况下会出错-我想它已经被修复了,但我需要对它进行更多的测试。我邀请您尝试最新的部分-我想我们已经修复了它。。。抱歉说得这么含糊,但有一个bug在3.0.0.1和3.0.0.3之间工作,我一直找不到它。

我们有一个bug,它的投影在某些情况下会出现问题-我想它已经被修补,但我需要进一步测试。我邀请您尝试最新的部分-我想我们已经修复了它。。。抱歉说得这么含糊,但有一个bug在3.0.0.1和3.0.0.3之间工作,我一直找不到它。

我想我已经找到了这个问题的实际答案。我一直在亚音速源中搜索,发现在将datareader映射到对象时使用了两种类型的对象投影:一种用于匿名类型和分组,另一种用于其他所有类型:

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

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;
请注意,[t0].[c0]与我的属性名NumberOfInstalls不同。所以c0的值永远不会投射到我的对象中

修复方法:
您只需取出if语句并使用10倍慢的投影,一切都会正常工作。

我想我已经找到了这个问题的实际答案。我一直在亚音速源中搜索,发现在将datareader映射到对象时使用了两种类型的对象投影:一种用于匿名类型和分组,另一种用于其他所有类型:

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

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;
请注意,[t0].[c0]与我的属性名NumberOfInstalls不同。所以c0的值永远不会投射到我的对象中

修复方法:
您只需取出if语句并使用速度慢10倍的投影,一切都会正常工作。

这在3.0.0.4中是否已修复?我发现这篇文章很生气。经过两天的努力,我终于明白了为什么我的预测不起作用——除非属性名称与查询完全匹配——我最终来到了这里。 我太依赖于SS SimpleRepository了,现在回头已经太晚了。像这样的虫子是残废的。有可能解决吗


我现在走的是慢10倍的路线,所以我至少可以向我的客户发布。您更希望使用更快的方法来正确工作:)

这在3.0.0.4中是否已修复?我发现这篇文章很生气。经过两天的努力,我终于明白了为什么我的预测不起作用——除非属性名称与查询完全匹配——我最终来到了这里。 我太依赖于SS SimpleRepository了,现在回头已经太晚了。像这样的虫子是残废的。有可能解决吗


我现在走的是慢10倍的路线,所以我至少可以向我的客户发布。更希望使用更快的方法来正确工作:)

在构造ReleaseInfo对象之前,您是否尝试过使用更简单的查询来创建临时变量(使用
let
)?即使从查询中取出let部分,我也会遇到同样的问题。您是否尝试过使用更简单的查询来创建临时变量(使用
let
)在构建ReleaseInfo对象之前?即使我从队列中取出let部分,我也会遇到同样的问题