Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Linq-如何在查询中使用函数_C#_Linq_Linq To Sql - Fatal编程技术网

C# Linq-如何在查询中使用函数

C# Linq-如何在查询中使用函数,c#,linq,linq-to-sql,C#,Linq,Linq To Sql,我在WP7芒果上使用C。我尝试使用特殊查询,因为我收到一个错误: 方法“Int32 orderBirthdaySystem.DateTime”不受支持 转换为SQL 是的,我知道。。。Linq不能使用我的功能,但我不知道正确的方法 我有一个包含列名称和生日的数据库表。在我的查询中,我将从所有项目中计算离下一个生日还有多少天,然后我将按降序排序 static int orderBirthday(DateTime Birthday) { DateTime today = Da

我在WP7芒果上使用C。我尝试使用特殊查询,因为我收到一个错误:

方法“Int32 orderBirthdaySystem.DateTime”不受支持 转换为SQL

是的,我知道。。。Linq不能使用我的功能,但我不知道正确的方法

我有一个包含列名称和生日的数据库表。在我的查询中,我将从所有项目中计算离下一个生日还有多少天,然后我将按降序排序

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);
.
.
.
}

这样做很容易:

    var toDoItemsInDB = from ToDoItem todo in toDoDB.Items.ToArray()
                        let daysToBirthday = orderBirthday(todo.ItemDate)
                        orderby daysToBirthday ascending
                        select todo.;

请注意添加到项目中的.ToArray。基本上,您可以将结果放入内存中,这样您的函数就可以工作。

您要么从数据库中提取所有内容,并按照谜一样在本地对其进行排序,要么找到在LINQ语句本身中表示排序操作的方法。由于您将排序行为提取到它自己的函数中,您可能希望重用此逻辑。在这种情况下,最好是创建一个过滤IQueryable的函数

以下是如何执行此操作的示例:

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;
}
也可以将其用作扩展方法:

var toDoItemsInDB = toDoDB.Items.OrderByBirthday();
两种方式:

第一:使用ToEnumerable将它从Linq2SQL拉到Linq2Object,然后在C级别使用orderBirthday

优点是它易于编码和维护,缺点是它的效率可能会降低,这取决于您正在做什么

第二:用SQL编写一个等价的函数,假设它名为dbo.orderBirth。将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.
}
这里,C代码用于非Linq2SQL上下文,SQL代码用于在Linq2SQL上下文中组合SQL查询

优点:可以在SQL中停留更长时间。缺点:同一方法的两个版本可能不同步并导致错误

也可以让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;
}

优点:保持一个版本的SQL作为唯一的版本,因此它不会与C版本不同步。缺点:即使在处理与SQL无关的对象时也调用SQL。

如果不希望加载内存中的所有项,并且希望数据库执行计算,您可以编写一个可以执行复杂计算的存储过程,并使用ADO或EF调用该过程。

但如果这样做,将失去Linq的流式处理能力。。。如果有许多结果,这可能会导致OutOfMemoryException。您应该使用一个numerable而不是array请注意,当Items表中的记录数开始增加时,这将开始执行错误操作,因为您将把该表的完整内容加载到内存中。@thomasleveque-我不喜欢AsEnumerable-它不做任何事情,您仍然可以强制转换回基础类型。这是一个愚蠢的实现。@Enigmativity,AsEnumerable没有任何作用,真的吗?它将序列的静态类型从IQueryable更改为IEnumerable,这样所有后续Linq运算符都将取自Enumerable而不是Queryable,因此查询将在内存中执行,而不是在DB中执行。即使它的实现是微不足道的,我不认为你可以说它什么都没做。。。关于对底层类型的强制转换:好的,那么toDoItemsInDB的底层类型是什么?它是System.Core程序集的一个内部类型,您无法强制转换到它,因为它不可访问…@ThomasLeveque-AsEnumerable的实现如下:public static IEnumerable AsEnumerable this IEnumerable source{return source;}。这就是为什么我说它什么都不做。除非我们讨论的是一个不同的AsEnumerable,否则它所做的一切都是cast。
[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;
}