Reputation: 27996
I have this query:
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
};
which is giving error:
LINQ to Entities does not recognize the method 'System.String GetAccountTypeDescription(System.String)' method, and this method cannot be translated into a store expression.
Function is :
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;
}
If I don't use GetAccountTypeDescription in LINQ query, It works.
Please suggest solution
Upvotes: 2
Views: 4568
Reputation: 26664
Edit - Adding a left join
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
};
Upvotes: 0
Reputation: 364279
You cannot use arbitrary function in linq-to-entities. It was explained many times. For example here. If you want to use custom function in Linq-to-entities query you must define it as SQL User defined function (UDF) in your database and map it.
First create function
CREATE FUNCTION dbo.udf_GetAccountTypeDescription (@Param VARCHAR(50))
RETRUNS VARCHAR(100)
AS
BEGIN
RETURN @Param + ' ' + 'Item type'
END
Now you must update your model and import the function (it will be listed among stored procedures). Once you have your function imported in SSDL (storage description in EDMX) you can map the function:
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.");
}
}
This function is only placeholder used in expression tree. It will be replaced by mapped SQL function when store provider translates expression tree to SQL query. Now you can use this in your Linq-to-entities query:
AccountTypeDescription = EdmFunctions.GetAccountTypeDescription("...")
Upvotes: 0
Reputation: 1563
I kind of don't understand this. Why don't You provide a property to the class/struct AccountReport that gives YOu AccountTypeDescription... That way You encapsulate the logic, hid the implementation details and generally make the code a lot kosher. Since the Accoutn description is just a transformation on the pulled data that is the best way to do. luke
Upvotes: 0
Reputation: 21713
You LINQ query is not run locally, but is turned into an expression (which is turned into SQL) and executed your database server. The expression parser cannot turn your function into SQL because that function doesn't exist on the server. You can only use LINQ and a few other .NET functions inside a LINQ query that is to be run on the database. You can easily fix this as such
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 };
Upvotes: 2