3

SQL クエリを Linq に変換しようとすると、例外が発生します。

System.NotSupportedException : ローカル コレクションを使用したクエリはサポートされていません。

それで、「合法的な」方法でクエリを言い換える方法はありますか?

ご提案ありがとうございます。

アンダース、デンマーク

PS: .Contains() を呼び出す前に任意のクエリで .ToList() を呼び出す「解決策」を見てきましたが、それでは 4 つの個別のクエリが発生するだけですよね?

下部にあるのは、実行時に失敗する私のコードです。

私が解決しようとしている論理的な問題は、直接アクセスするか、アクセス権を持つグループのメンバーシップによって、ユーザーがアクセスできる「構造」を見つけることです。ネストされたグループはありません。

つまり、次のいずれかに該当する場合、ユーザーはアクセス権を持つ必要があります。

  • ユーザーが構造を作成しました (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を見つけようとしており、それらをアプリケーション層に持ってきています。

おそらく、すべての loginc を SQL 関数または SP にプッシュし、最終結果をアプリケーション レイヤーのみに取得した方がよいでしょうか?

于 2013-01-04T13:35:17.520 に答える