используя функцию в Linq - PullRequest
2 голосов
/ 13 мая 2011

У меня есть этот запрос:

var accounts =
    from account in context.Accounts
    from owner in account.AccountOwners
    join business in context.Businesses
        on account.CreditRegistryId
        equals business.RegistryId
    join astatus in context.AccountStatuses
        on account.AccountStatusId
        equals astatus.AccountStatusId     
    join LS in context.LegalStatuses
        on account.LegalStatusId 
        equals LS.LegalStatusId
    where !excludeTypes.Contains(account.AccountType)               
    select new AccountsReport
    {
        AccountTypeDescription = GetAccountTypeDescription(account.AccountType),  
        AccountNumber = 1, 
        AccountStatus = "aasd", 
        CreditorAddress = "address", 
        CreditorCity = "my city", 
        CreditorName = "creditor name", 
        CreditorState = "my state", 
        LegalStatus = "my status", 
        RegistryId = 121323
    };

, который выдает ошибку:

LINQ to Entities does not recognize the method 'System.String GetAccountTypeDescription(System.String)' method, and this method cannot be translated into a store expression. 

Функция:

public string GetAccountTypeDescription(string accountType)
{
    var result = context.AccountTypes.Where(x => x.AccountTypeCode == accountType).Select(x => x.Abbreviation).SingleOrDefault();

    if (string.IsNullOrEmpty(result))
    {
        result = accountType;
    }

    return result;
}

Если я не использую GetAccountTypeDescriptionв запросе LINQ, это работает.

Пожалуйста, предложите решение

Ответы [ 4 ]

2 голосов
/ 13 мая 2011

Ваш запрос LINQ не выполняется локально, а превращается в выражение (которое превращается в SQL) и выполняет ваш сервер базы данных. Анализатор выражений не может превратить вашу функцию в SQL, потому что эта функция не существует на сервере. Вы можете использовать только LINQ и несколько других функций .NET внутри запроса LINQ, который должен выполняться в базе данных. Вы можете легко исправить это как таковое

var accountDescription = GetAccountTypeDescription("sdfsdf");
var accounts =
            from account in context.Accounts
            from owner in account.AccountOwners
             join business in context.Businesses
             on account.CreditRegistryId
             equals business.RegistryId
             join astatus in context.AccountStatuses
             on account.AccountStatusId
             equals astatus.AccountStatusId     
             join LS in context.LegalStatuses
             on account.LegalStatusId 
             equals LS.LegalStatusId
             where !excludeTypes.Contains(account.AccountType)               
            select new AccountsReport { AccountTypeDescription= accountDescription,  AccountNumber = 1, AccountStatus = "aasd", CreditorAddress = "address", CreditorCity = "my city", CreditorName = "creditor name", CreditorState = "my state", LegalStatus = "my status", RegistryId = 121323 };
0 голосов
/ 13 мая 2011

Вы не можете использовать произвольную функцию в linq-to-entity. Это объяснялось много раз. Например, здесь . Если вы хотите использовать пользовательскую функцию в запросе Linq-to-entity, вы должны определить ее как пользовательскую функцию SQL (UDF) в вашей базе данных и отобразить ее.

Первая функция создания

CREATE FUNCTION dbo.udf_GetAccountTypeDescription (@Param VARCHAR(50))
RETRUNS VARCHAR(100)
AS
BEGIN
    RETURN @Param + ' ' + 'Item type'
END

Теперь вы должны обновить модель и импортировать функцию (она будет указана среди хранимых процедур). После того как ваша функция импортирована в SSDL (описание хранилища в EDMX), вы можете отобразить функцию:

public static class EdmFunctions
{
    // First parameter is namespace of SSDL (open EDMX as XML if you are not sure about namespace)
    [EdmFunction("TestModel.Store", "udf_GetAccountTypeDescription")]
    public static string GetAccountTypeDescription(string parameter)
    {
        throw new NotSupportedException("This function is only for L2E query.");
    }
}

Эта функция является только заполнителем, используемым в дереве выражений. Он будет заменен сопоставленной функцией SQL, когда провайдер магазина преобразует дерево выражений в запрос SQL. Теперь вы можете использовать это в своем запросе Linq-to-entity:

AccountTypeDescription = EdmFunctions.GetAccountTypeDescription("...")
0 голосов
/ 13 мая 2011

Я вроде не понимаю этого. Почему бы вам не предоставить свойство классу / структуре AccountReport, которое дает вам AccountTypeDescription ... Таким образом, вы инкапсулируете логику, скрываете детали реализации и, как правило, делаете код намного кошернее. Поскольку описание Accoutn - это просто преобразование извлеченных данных, это лучший способ сделать это. * 1001 Лука *

0 голосов
/ 13 мая 2011

Редактировать - добавление левого соединения

var accounts =
    from account in context.Accounts
    from owner in account.AccountOwners
    join business in context.Businesses
        on account.CreditRegistryId
        equals business.RegistryId
    join astatus in context.AccountStatuses
        on account.AccountStatusId
        equals astatus.AccountStatusId     
    join LS in context.LegalStatuses
        on account.LegalStatusId 
        equals LS.LegalStatusId
    from accountType in context.AccountTypes
                               .Where(at => at.AcountTypeCode == account.AccountType)
                               .DefaultIfEmpty()
    where !excludeTypes.Contains(account.AccountType)               
    select new AccountsReport
    {
        AccountTypeDescription = accountType.Abbreviation == null ? account.AccountType : accountType.Abbreviation,  
        AccountNumber = 1, 
        AccountStatus = "aasd", 
        CreditorAddress = "address", 
        CreditorCity = "my city", 
        CreditorName = "creditor name", 
        CreditorState = "my state", 
        LegalStatus = "my status", 
        RegistryId = 121323
    };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...