Вставить Funcзначение в запросе linq-2-sql - PullRequest
2 голосов
/ 13 февраля 2012

У меня мультитенантное приложение, и все данные находятся в одной базе данных. Мы разделяем данные для каждого арендатора по таблице objectToTenant.

В общем классе репозитория я хочу реализовать метод, который фильтрует объекты, просто указывая, какое свойство объекта является tenantToObjectRelationId и какой тип является объектом (необходимо, поскольку в таблице отношений хранятся различные типы)

Звонок, который я хочу сделать, должен выглядеть следующим образом:

// Specialized Repository class 
var allItemsForTenant =
    this.AllForTenant(item => item.RelationId, 123);

и поэтому я реализовал этот метод:

// Generic Repository class
public virtual IQueryable<T> AllForTenant(
    Func<T, int> getObjectToTenantRelationId, string objectType)
{
    var result =
        from item in this.context.GetTable<T>( )
        join tenantObject in (
            from tenantRelationRecord in objectTenantRelationRepo.All( )
            where tenantRelationRecord.TenantId == Global.TenantId
            where tenantRelationRecord.ObjectTypeId == type.TypeId
            select tenantObjectRecord)
            on getObjectToTenantRelationId( item ) equals tenantObject.ObjectId
        select item;

    return result;
}

но в данный момент я получаю NotSupportedException

Описание System.Object DynamicInvoke (System.Object []) - методические указания keine unterstützte Übersetzung в SQL.

, вызванный методом Func<T, int>, который не может быть переведен в sql.

Как мне нужно изменить Func<T, int>, чтобы его можно было перевести, или у кого-то есть другое решение?

Ответы [ 2 ]

0 голосов
/ 13 февраля 2012

Самое простое решение - передать Expression<Func<T,int>> вместо Func<T,int>. Передача выражения позволит посетителю дерева «войти» в ваше выражение, а не отскочить от его имени.

Что приятно, если вы передадите лямбда-выражения, компилятор автоматически создаст из них Expression<Func<T,int>>, поэтому единственное, что вам нужно изменить, - это подпись вашего AllForTenant метода.

0 голосов
/ 13 февраля 2012

Вместо передачи в Func<T, int> проход в IQueryable<Tuple<T, int>> или что-то подобное.Таким образом, LINQ to SQL знает, как перевести его на SQL:

// Generic Repository class
public virtual IQueryable<T> AllForTenant(
    IQueryable<Tuple<T, int>> objectToTenentRelationIds, string objectType)
{
    var tenantObjects =
        from tenantRelationRecord in objectTenantRelationRepo.All()
        where tenantRelationRecord.TenantId == Global.TenantId
        where tenantRelationRecord.ObjectTypeId == type.TypeId
        select tenantObjectRecord;

    var result =
        from item in this.context.GetTable<T>()
        join objectToTenentRelationId in objectToTenentRelationIds
            on objectToTenentRelationId.Item1 equals item
        join tenantObject in tenantObjects
            on objectToTenentRelationIds.Item2 equals tenantObject.ObjectId
        select item;

    return result;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...