11-12. 定義內置函數問題想要定義一個在eSQL 和LINQ 查詢里使用的內置函數.解決方案我們要在資料庫中使用IsNull 函數,但是EF沒有為eSQL 或LINQ發佈這個函數. 假設我們已有一個WebProduct實體模型,如Figure 11-12所示.Figure 11-12. A We...
11-12. 定義內置函數
問題
想要定義一個在eSQL 和LINQ 查詢里使用的內置函數.
解決方案
我們要在資料庫中使用IsNull 函數,但是EF沒有為eSQL 或LINQ發佈這個函數. 假設我們已有一個WebProduct實體模型,如Figure 11-12所示.
Figure 11-12. A WebProduct entity in our model
為我們的查詢發佈函數:
1. 在解決方案資源管理器里右擊.edmx 文件, 打開方式 ➤ XML 編輯器.
2.在.edmx 文件的存儲模型(storage models)節里<Schema>標簽下,插入如Listing 11-19所示 的代碼. 這樣我們就在存儲層定義好了函數.
Listing 11-19. Defining Our Function in the Storage Layer
<Function Name="ISNULL" ReturnType="varchar" BuiltIn="true" Schema="dbo">
<Parameter Name="expr1" Type="varchar" Mode="In" />
<Parameter Name="expr2" Type="varchar" Mode="In" />
</Function>
3.插入和查詢模型的代碼如下列的Listing 11-19所示.
Listing 11-20. Using the ISNULL() Function in an eSQL and LINQ Query
class Program
{
static void Main(string[] args)
{
RunExample();
}
static void RunExample()
{
using (var context = new EFRecipesEntities())
{
context.Database.ExecuteSqlCommand("delete from chapter11.webproduct");
var w1 = new WebProduct
{
Name = "Camping Tent",
Description = "Family Camping Tent, Color Green"
};
var w2 = new WebProduct { Name = "Chemical Light" };
var w3 = new WebProduct
{
Name = "Ground Cover",
Description = "Blue ground cover"
};
context.WebProducts.Add(w1);
context.WebProducts.Add(w2);
context.WebProducts.Add(w3);
context.SaveChanges();
}
using (var context = new EFRecipesEntities())
{
Console.WriteLine("Query using eSQL...");
var esql = @"select value
EFRecipesModel.Store.ISNULL(p.Description,p.Name)
from EFRecipesEntities.WebProducts as p";
var objectContext = (context as IObjectContextAdapter).ObjectContext;
var prods = objectContext.CreateQuery<string>(esql);
foreach (var prod in prods)
{
Console.WriteLine("Product Description: {0}", prod);
}
}
using (var context = new EFRecipesEntities())
{
Console.WriteLine();
Console.WriteLine("Query using LINQ...");
var prods = from p in context.WebProducts
select BuiltinFunctions.ISNULL(p.Description, p.Name);
foreach (var prod in prods)
{
Console.WriteLine(prod);
}
}
}
}
public class BuiltinFunctions
{
[EdmFunction("EFRecipesModel.Store", "ISNULL")]
public static string ISNULL(string check_expression, string replacementvalue)
{
throw new NotSupportedException("Direct calls are not supported.");
}
}
上述Listing 11-20 代碼輸出結果如下:
Query using eSQL...
Product Description: Family Camping Tent, Color Green
Product Description: Chemical Light
Product Description: Blue ground cover
Query using LINQ...
Family Camping Tent, Color Green
Chemical Light
Blue ground cover
它是如何工作的?
如Listing 11-18所示 的 ISNULL() 函數的定義,函數名必須與資料庫里的函數名一致(大小寫不必一致), 這次不像本章前面小節的函數在概念層定義, 是在數據存儲層. 這個函數原本在資料庫里就是可用的,我們只是簡單的在存儲層定義一下.當在eSQL 語句中使用該函數時,必須使用完整的命名空間.( EFRecipesModel.Store.ISNULL()).當在LINQ查詢中使用該函數時,需創建引導方法,由於不返回IQueryable<T>類型,所以不必實現方法體.