[英]Linq - how can I use a function in a query
I use C# on WP7 (Mango). 我在WP7(芒果)上使用C#。 I try to use a special query because I receive an error:
我尝试使用特殊查询,因为收到错误:
Method 'Int32 orderBirthday(System.DateTime)' has no supported translation to SQL.
方法'Int32 orderBirthday(System.DateTime)'不支持SQL转换。
Yes, I know... Linq can't use my function but I don't know the right way... 是的,我知道... Linq无法使用我的函数,但我不知道正确的方法...
I have a database table with the columns name
and birthday
. 我有一个数据库表,其中包含
name
和birthday
列。 In my query I will calculate how many days are to the next birthday (from all items) and then I will order with "descending". 在我的查询中,我将计算(从所有项目中)到下一个生日有几天,然后我将按“降序”排序。
static int orderBirthday(DateTime Birthday)
{
DateTime today = DateTime.Today;
DateTime birthday = Birthday;
DateTime next = new DateTime(today.Year, birthday.Month, birthday.Day);
if (next < today)
next = next.AddYears(1);
int numDays = (next - today).Days;
// No Conversion
return numDays;
}
public void LoadCollectionsFromDatabase()
{
DateTime today = DateTime.Today;
var toDoItemsInDB = from ToDoItem todo in toDoDB.Items
let daysToBirthday = orderBirthday(todo.ItemDate)
orderby daysToBirthday ascending
select todo;
// Query the database and load all to-do items.
AllToDoItems = new ObservableCollection<ToDoItem>(toDoItemsInDB);
.
.
.
}
You either have to pull everything from the database and sort it locally (as Enigmativity) shows, or find a way to express the sort operation in a LINQ statement itself. 您要么必须从数据库中提取所有内容并对其进行本地排序(如Enigmativity所示),要么必须找到一种方法来表达LINQ语句本身中的排序操作。 And since you extracted the sorting behavior into its own function, you probably want to reuse this logic.
并且由于将排序行为提取到了自己的函数中,因此您可能想重用此逻辑。 In that case your best bet is to create a function that filters an
IQueryable
. 在这种情况下,最好的选择是创建一个过滤
IQueryable
的函数。
Here is an example of how to do this: 这是如何执行此操作的示例:
public static IOrderedQueryable<Item> OrderByBirthday(
this IQueryable<Item> items)
{
return
from item in items
let today = DateTime.Today
let birthday = item.ItemDate
let next = new DateTime(today.Year, birthday.Month, birthday.Day)
let next2 = next < today ? next.AddYears(1) : next
orderby (next - today).Days
select item;
}
You can use the method as follows: 您可以使用以下方法:
var toDoItemsInDB = OrderByBirthday(toDoDB.Items);
Or you can use it as an extension method: 或者,您可以将其用作扩展方法:
var toDoItemsInDB = toDoDB.Items.OrderByBirthday();
It's easy if you do this: 如果这样做,这很容易:
var toDoItemsInDB = from ToDoItem todo in toDoDB.Items.ToArray()
let daysToBirthday = orderBirthday(todo.ItemDate)
orderby daysToBirthday ascending
select todo.;
Notice the .ToArray()
added to Items
. 注意将
.ToArray()
添加到Items
。 You basically bring the results into memory and them your function can work. 您基本上将结果存储到内存中,并且您的函数可以使用它们。
Two ways: 两种方式:
One: Pull it from Linq2SQL to Linq2Objects using ToEnumerable()
, and then use orderBirthday
at the C# level. 一:使用
ToEnumerable()
将它从Linq2SQL拉到ToEnumerable()
,然后在C#级别使用orderBirthday
。
Advantage is that it's simple to code and maintain, disadvantage is that it can be less efficient (depends on just what you are doing. 优点是它的简单编码和维护,缺点是,它可以是低效率的(取决于你在做什么。
Two: Write an equivalent function in SQL, let's say it was called dbo.orderBirthday
. 二:在SQL中编写一个等效的函数,假设它称为
dbo.orderBirthday
。 Make your orderBirthday
method a non-static method of your datacontext-derived class, and then mark your method as having a SQL function equivalent: 使您的
orderBirthday
方法成为datacontext派生类的非静态方法,然后将您的方法标记为具有与SQL函数等效的方法:
[Function(Name="dbo.orderBirthday",IsComposable=true)] //IsComposable is true for functions that can be used within queries, false for stored procedures that must be called on their own.
public int OrderBirthday([Parameter(Name="@birthday",DbType="datetime") DateTime birthday)
{
return Helper.OrderBirthday(birthday); // just to show that we can keep the static version around if we want and call into it. Alternatively we could just move the whole body here.
}
Here the C# code is used in a non-Linq2SQL context, and the SQL code is used in composing a SQL query in a Linq2SQL context. 此处,C#代码用于非Linq2SQL上下文,而SQL代码用于在Linq2SQL上下文中构成SQL查询。
Advantage: Can stay within SQL longer. 优点:可以在SQL中停留更长时间。 Disadvantage: Two versions of the same method can fall out of sync and cause bugs.
缺点:相同方法的两个版本可能会不同步并导致错误。
It's also possible to have the C# code call the SQL code all the time: 也可能总是让C#代码调用SQL代码:
[Function(Name="dbo.orderBirthday",IsComposable=true)]
public int OrderBirthday([Parameter(Name="@birthday",DbType="datetime") DateTime birthday)
{
return (int)ExecuteMethodCall(this, (MethodInfo)MethodInfo.GetCurrentMethod(), birthday).ReturnValue;
}
Advantage: Keeps one version (the SQL) as the only version, so it can't fall out of synch with the C# version. 优点:将一个版本(SQL)保留为唯一版本,因此它不会与C#版本不同步。 Disadvantage: Calls SQL even when working on objects that have nothing to do with SQL.
缺点:即使在处理与SQL无关的对象时也调用SQL。
如果您不想将所有项目都加载到内存中,并且希望数据库执行计算,则可以编写一个可以执行复杂计算的存储过程,并使用ADO或EF调用该过程。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.