实体框架6.1.1 DbJoinExpression获取所有左列



我试图得到一个表达式树访问者添加一个连接到另一个表时,某些实体查询。如果我包含一个投射到匿名类型的.Select()方法,并直接指定正在查询的特定实体的列,则表达式将非常有效:

var joinEntity = expression.Target.EntityContainer.BaseEntitySets.Single(s => s.Name == "TestJoinTable");
return expression.InnerJoin(
    DbExpressionBuilder.Scan(joinEntity),
        (l, r) => DbExpressionBuilder.And(
                DbExpressionBuilder.Equal(
                    DbExpressionBuilder.Property(l, "JoinId"),
                    DbExpressionBuilder.Property(r, "JoinId")
                )
                , DbExpressionBuilder.Equal(
                    DbExpressionBuilder.Property(r, "UserId"),
                    DbExpression.FromInt32(_userId)
                )
            )
        )
    .Select(exp =>
        new { // these are the 3 columns from one specific entity I have called Resources
                ResourceId = exp.Property("l").Property("ResourceId"),
                ResourceName = exp.Property("l").Property("ResourceName"),
                JoinId = exp.Property("l").Property("JoinId"),
            }
    );

在这种特殊情况下导致这个表达式逻辑运行的LINQ to entities查询是:

List<Resource> resources = db.Resources.ToList();

问题是,表达式访问器代码旨在针对许多不同的实体查询运行,而不仅仅是针对资源实体查询。我需要一个动态的方式来选择所有列从左边的实体。我需要指定如下内容:

.Select( exp => exp.Property("l").Property("*") )

上面的表达式不能编译。它抛出错误:No property with the name '*' is declared by the type 'ScratchDbModel.Store.Resource' .

我也试过了,但是它失败了,出现了类似的错误信息:

.Select( exp => exp.Property("l.*") )

我试着只选择左边的实体,像这样:

.Select( exp => exp.Property("l") )
上面的表达式编译后看起来很有希望,直到它实际运行查询,结果如下SQL:
SELECT 
    [Extent1].[ResourceId] AS [ResourceId], 
    [Extent1].[ResourceName] AS [ResourceName], 
    [Extent1].[JoinId] AS [JoinId]
    FROM ( SELECT [l]
        FROM  [dbo].[Resource] AS [l]
        INNER JOIN [sec].[TestJoinTable] AS [r]
    ON ([l].[JoinId] = [r].[JoinId]) AND ([r].[UserId] = 2)
    )  AS [Extent1]

由于内部SELECT选择的是[l]而不是[l.*]或列名列表,因此查询执行失败,并显示以下消息:

Invalid column name 'l'.
Invalid column name 'ResourceId'.
Invalid column name 'ResourceName'.
Invalid column name 'JoinId'.

我已经尝试了许多不同的事情,但似乎不知道如何做到这一点。如果我完全离开.Select(),我收到错误:

An exception of type 'System.ArgumentOutOfRangeException' occurred in EntityFramework.dll but was not handled in user code
Additional information: No property with the name 'ResourceId' is declared by the type 'Transient.rowtype[(l,ScratchDbModel.Store.Resource(Nullable=True,DefaultValue=)),(r,ScratchDbModel.Store.TestJoinTable(Nullable=True,DefaultValue=))]'.

当然,这是因为实体框架期望接收IEnumerable<Resource>,而不是一些多表连接结果。

是否有任何方法可以通用地指定"左表的所有列"或创建某种类型的动态匿名类型或动态投影,其中包含左实体的所有列引用?

要选择属性的所有属性,只需选择它的整体:

return expression.InnerJoin(
    DbExpressionBuilder.Scan(joinEntity),
        (l, r) => DbExpressionBuilder.Equal(
                    DbExpressionBuilder.Property(l, "JoinId"),
                    DbExpressionBuilder.Property(r, "JoinId")
                )
    )
    .Select(exp => exp.Property("l"));

这将自动生成查询,选择"l"拥有的所有列。

相关内容

  • 没有找到相关文章

最新更新