Entity Framework 4 (EF4) 和 ESQL 查询示例

在使用Entity Framework4 (EF4) 及其ESQL查询语法时,执行查询后通常会得到一个DbDataRecord对象集合。这种情况通常发生在查询返回一个匿名类型时。DbDataRecord对象让想起了ADO.NET中的DbDataReader,它是一个抽象项,可以包含任何内容。要获取数据,只需遍历DbDataReader并按列名或索引获取数据。

环境

本文使用的环境包括:

使用ESQL进行查询

将展示3个示例,从简单到复杂,展示如何将DbDataRecord转换为自定义的类型。

让先获取一些类型化数据,比如所有客户信息。使用

SELECT VALUE item FROM

类似于T-SQL中的SELECT * FROM,但同时指定了结果的特定类型,本例中为Customer

using (AdventureWorksLT2008Entities ctx = new AdventureWorksLT2008Entities()) { string query = string.Format("SELECT VALUE item FROM {0}.Customers AS item", ctx.DefaultContainerName); ObjectQuery customersQuery = new ObjectQuery(query, ctx); }

现在想要获取所有记录,但只包含FirstNameLastNameCompanyName列。如果尝试使用之前的代码并仅更改查询,EF4会给出错误提示,因为无法将System.Data.Objects.MaterializedDataRecord类型转换为Customer类型。要解决这个问题,必须使用ObjectQuery<DbDataRecord>

using (AdventureWorksLT2008Entities ctx = new AdventureWorksLT2008Entities()) { string query = string.Format("SELECT item.FirstName, item.LastName, item.CompanyName FROM {0}.Customers AS item", ctx.DefaultContainerName); ObjectQuery customersQuery = new ObjectQuery(query, ctx); }

现在有了所有数据作为匿名类型,而不是Customer类型。这在仅需要显示/使用原始数据时很好,但如果想要将这些匿名类型列表转换为客户列表呢?如果更进一步,想要获取一个自定义类型的列表,而这个类型恰好具有与查询中检索的列同名的属性呢?没问题,只需使用这些扩展方法即可。

public static class AnonymousTypeConversion { public static T ConvertTo(this DbDataRecord record) { T item = Activator.CreateInstance(); for (int f = 0; f < record.FieldCount; f++) { PropertyInfo p = item.GetType().GetProperty(record.GetName(f)); if (p != null && p.PropertyType == record.GetFieldType(f)) { p.SetValue(item, record.GetValue(f), null); } } return item; } public static List ConvertTo(this List list) { List result = (List)Activator.CreateInstance>(); list.ForEach(rec => { result.Add(rec.ConvertTo()); }); return result; } }

现在,让创建一个自定义的Customer类型,它具有更少的属性,并添加一个名为FullName的新属性,该属性仅连接FirstNameLastName

public class TinyCustomer { public string FirstName { get; set; } public string LastName { get; set; } public string CompanyName { get; set; } public string FullName { get { return (string.IsNullOrEmpty(FirstName) ? string.Empty : FirstName) + " " + (string.IsNullOrEmpty(LastName) ? string.Empty : LastName); } } }

让从匿名查询中获取TinyCustomer的列表。

using (AdventureWorksLT2008Entities ctx = new AdventureWorksLT2008Entities()) { string query = string.Format("SELECT item.FirstName, item.LastName, item.CompanyName FROM {0}.Customers AS item", ctx.DefaultContainerName); ObjectQuery customersQuery = new ObjectQuery(query, ctx); lblQueryString.Text = query; var tinyCustomers = customersQuery.ToList().ConvertTo(); }

计划很快写一篇关于EF4/ESQL动态查询的文章,发现这特别有用。做了一个包含本文所有代码的示例项目,只需下载示例项目,在SQL Server实例上安装AdventureWorks数据库,并在web.config中配置连接字符串。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485