如何使用C#LINQ查询调用SQLite用户定义函数

如何使用C#LINQ查询调用SQLite用户定义函数,c#,linq,sqlite,linq-to-entities,udf,C#,Linq,Sqlite,Linq To Entities,Udf,对于SQLite和C#,是否有人尝试在LINQ查询中调用UDF 在网上搜索时,我发现这是关于在C中创建UDF函数的# 至于在LINQ中调用一个函数来调用实体,我这里有一个解决方案 这是我到目前为止得到的。我创建了我的数据库模型,并将linq转换为SQLite 我将其添加到数据库模型文件中: <Function Name="fn_CalculateSomething" Aggregate="false" BuiltIn="false" NiladicFunction="false" Is

对于SQLite和C#,是否有人尝试在LINQ查询中调用UDF

在网上搜索时,我发现这是关于在C中创建UDF函数的#

至于在LINQ中调用一个函数来调用实体,我这里有一个解决方案

这是我到目前为止得到的。我创建了我的数据库模型,并将linq转换为SQLite

我将其添加到数据库模型文件中:

<Function Name="fn_CalculateSomething" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="true" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo" ReturnType="real">
  <Parameter Name="height" Type="real" Mode="In" />
  <Parameter Name="depth" Type="real" Mode="In" />
</Function>
我得到这个错误

The specified method 'System.Nullable`1[System.Single] fn_CalculateSomething(Single, Single)' on the type 'SQLiteTest.MyModelTable' cannot be translated into a LINQ to Entities store expression because its return type does not match the return type of the function specified by its DbFunction attribute.
Unable to cast object of type 'System.Data.Entity.DynamicProxies.MyModelTable_935D452DE6F9E3375A6D180DF5A662168FD2DE164BA93C588D9CDCA1909630EB' to type 'System.Data.Entity.Infrastructure.IObjectContextAdapter'.
如果我尝试这个代码

public partial class MyModelTable {
    [DbFunction("MyModel.Store", "fn_CalculateSomething")]
    public float? DbGetValue(float height, float depth, float ratio) {
        List<ObjectParameter> parameters = new List<ObjectParameter>(3);
        parameters.Add(new ObjectParameter("height", height));
        parameters.Add(new ObjectParameter("depth", depth));
        var lObjectContext = ((IObjectContextAdapter)this).ObjectContext;
        var output = lObjectContext.
             CreateQuery<float>("MyModel.Store.fn_CalculateSomething(@height, @depth)", parameters.ToArray())
            .Execute(MergeOption.NoTracking)
            .FirstOrDefault();
        return output;
    }
}

[SQLiteFunction(Name = "fn_CalculateSomething", Arguments = 2, FuncType = FunctionType.Scalar)]
public class fn_CalculateSomething : SQLiteFunction {
    public override object Invoke(object[] args) {
        float Height = (float)args[0];
        float Depth = (float)args[1];
        return Height * Depth;
    }
}
listBox1.DataSource = (from v in context.MyModelTable
                        select v.fn_CalculateSomething(5, 5)).ToList();
context.MyModelTable.First().fn_CalculateSomething(5, 5);
我得到这个错误

The specified method 'System.Nullable`1[System.Single] fn_CalculateSomething(Single, Single)' on the type 'SQLiteTest.MyModelTable' cannot be translated into a LINQ to Entities store expression because its return type does not match the return type of the function specified by its DbFunction attribute.
Unable to cast object of type 'System.Data.Entity.DynamicProxies.MyModelTable_935D452DE6F9E3375A6D180DF5A662168FD2DE164BA93C588D9CDCA1909630EB' to type 'System.Data.Entity.Infrastructure.IObjectContextAdapter'.

从这里我能做什么?

呜呼!我让它工作了

首先,DbGetValue函数在构建查询时不会被调用,只有在代码中直接调用时才会被调用。因此,其中的代码是不相关的,当它被调用时,您可以直接计算值,而无需调用数据库

第二,即使函数在模型中被定义为“real”,如果将返回值改为double而不是float,它也会工作。不知道为什么

第三,您必须使用类似以下内容将函数绑定到连接

public static class ExtensionMethods {
    public static void BindFunction(this SQLiteConnection connection, SQLiteFunction function) {
        var attributes = function.GetType().GetCustomAttributes(typeof(SQLiteFunctionAttribute), true).Cast<SQLiteFunctionAttribute>().ToArray();
        if (attributes.Length == 0) {
            throw new InvalidOperationException("SQLiteFunction doesn't have SQLiteFunctionAttribute");
        }
        connection.BindFunction(attributes[0], function);
    }
}
using (NaturalGroundingVideosEntities context = new NaturalGroundingVideosEntities()) {
    SQLiteConnection Conn = (SQLiteConnection)context.Database.Connection;
    Conn.Open();
    Conn.BindFunction(new fn_CalculateSomething());

    listBox1.DataSource = (from v in context.RatingCategories
                                   select v.DbGetValue(5, 5, 5)).ToList();
}
这会有用的!然后,您可能希望在一个更方便的位置进行函数绑定,但是您知道了

祝你好运