2015-05-28 104 views
0

有了SQLite和C#,有沒有人試圖在LINQ查詢中調用UDF?如何用C#LINQ查詢調用SQLite用戶定義函數

網上搜索,我發現這個約在C#創建一個UDF的功能調用在LINQ到實體功能

http://www.ivankristianto.com/howto-make-user-defined-function-in-sqlite-ado-net-with-csharp/

,我這裏有解決方案

Calling DB Function with Entity Framework 6

這是我到目前爲止。我創建我的數據庫模型和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> 

我添加此代碼

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(); 

我得到這個錯誤

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. 

如果我試試這個代碼

context.MyModelTable.First().fn_CalculateSomething(5, 5); 

我得到這個錯誤

Unable to cast object of type 'System.Data.Entity.DynamicProxies.MyModelTable_935D452DE6F9E3375A6D180DF5A662168FD2DE164BA93C588D9CDCA1909630EB' to type 'System.Data.Entity.Infrastructure.IObjectContextAdapter'. 

我可以在這裏做什麼?

回答

0

嗚呼!我得到了它的工作。

首先,只有在代碼中直接調用DbGetValue函數時纔會調用構建查詢。所以它裏面的代碼是不相關的,當它被調用時,你可以直接計算值而不用調用數據庫。其次,即使函數在模型中被定義爲「真實」,但如果將返回值更改爲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(); 
} 

這將工作!然後,你可能想在一個更方便的位置做功能綁定,但你明白了。

祝你好運!

相關問題