3

我正在尝试将 SQL 查询转换为 Linq,但出现异常:

System.NotSupportedException :不支持使用本地集合的查询。

那么有没有办法以“合法”的方式重新表述查询?

感谢您的任何建议,

丹麦安德斯

PS:在调用 .Contains() 之前,我已经看到在任何查询上调用 .ToList() 的“解决方案”——但这只会导致四个单独的查询,对吧?

底部是我执行失败的代码。

我试图解决的逻辑问题是找到用户可以访问的“结构”,无论是通过直接访问还是通过具有访问权限的组的成员身份。我们没有嵌套组。

换句话说,如果以下任何一项为真,则用户应该有权访问:

  • 用户创建了结构(id 被“标记”到结构记录中)。
  • PermissionUsers 表中存在一个条目,将 Permissions 表与 users 表链接起来。
  • PermissionGroups 表中存在一个条目,将 Permissions 表与 Groups 表链接,并且在 UsersGroups 表中引用了用户,将 Users 表与 Users 表链接。

将权限/限制结果应用于可访问的项目是一个相对较新的事情,我们希望数据库能够完成繁重的工作;)。

[TestFixture]
public class LinqTest : CommandBasedIntegrationTestBase
{
    [Test, Category("SuperIntegration"), RequiresSTAAttribute]
    public void TestThat()
    {
        DbIntegrationTestHelper.SetState();

        var dataContextProvider = ObjectFactory.GetInstance<IDataContextProvider>();

        const int userId = 1;

        var environment = ObjectFactory.GetInstance<IState>().DatabaseEnvironment;
        var dataClasses1DataContext = dataContextProvider.GetContext(environment);

        var idsByCreator = from r in dataClasses1DataContext.Structures where r.CreatedUserId == userId select r.StructureId;
        var idsByUserAccess = from r in dataClasses1DataContext.PermissionUsers where r.UserId == userId select r.StructureId;
        var idsOfGroupsContainingUser = from r in dataClasses1DataContext.UsersGroups where r.UserId == userId select r.GroupId;
        var idsByGroupAccess = from r in dataClasses1DataContext.PermissionGroups where idsOfGroupsContainingUser.Contains( r.GroupId ) select r.StructureId;


        var res = from s in dataClasses1DataContext.Structures
                  where
                      idsByCreator.Contains(s.StructureId) || 
                      idsByUserAccess.Contains(s.StructureId) ||
                      idsByGroupAccess.Contains(s.StructureId)
                  select s;

        foreach (var structure in res)
        {
            Debug.WriteLine(structure.Name);
        }
    }
}
4

2 回答 2

1

试一试JOINs, UNIONs

例子

var ctx = dataContextProvider.GetContext(environment);

var byCreator = from r in ctx.Structures where r.CreatedUserId == userId select r;

var byUserAccess = from r in ctx.PermissionUsers 
                   join s in ctx.Structures on r.StructureId equals s.StructureId
                   where r.UserId == userId select s;

var byGroups = from ug in ctx.UsersGroups 
               join pg in ctx.PermissionGroups on ug.GroupId equals pg.GroupId
               join s in ctx.Structures on pg.StructureId equals s.StructureId
               where ug.UserId == userId select s;

var res = byCreator.Union(byUserAccess).Union(byGroups);

更新

Distinct()根据@Magnus 的评论,我已经删除了不必要的调用。仅当使用代替Distinct()时才需要调用。Concat()Union()

于 2013-01-04T13:38:19.877 回答
0

正如我所看到的,您正在尝试在数据库表中查找s.StructureId并将它们带到应用程序层。

也许您最好将所有登录信息推送到 SQL 函数或 SP 中,并仅将最终结果发送到应用程序层?

于 2013-01-04T13:35:17.520 回答