本示例程序演示使用ADO.NET Entity Framework 创建Entity Data Model,然后如何使用Entity Client、Entity SQL 访问Entity Data Model,如何使用对象服务(Object Service)和LINQ to Entities 访问 Entity Data Model。并结合WPF 客户端,演示查询、更新、插入、删除数据记录等等。范例采用AdventureWorksLT 数据库。
示例程序运行界面如下:
范例程序下载(在底部)!
示例代码分析:
1. 填充Product Category 下拉列表框
下面的代码采用Entity SQL,通过Entity Client 访问EDM,返回全部Category 实体集合。
public IList<Category> GetCategories()
{
IList<Category> result = null;
EntityDataReader rdr;
EntityCommand cmd;
string esqlQuery;
using (EntityConnection conn = new EntityConnection("name=AdventureWorksLTEntities"))
{
conn.Open();
esqlQuery = @"SELECT VALUE c FROM AdventureWorksLTEntities.Category AS c";
result = new List<Category>();
cmd = conn.CreateCommand();
cmd.CommandText = esqlQuery;
rdr = cmd.ExecuteReader(CommandBehavior.SequentialAccess);
while (rdr.Read())
{
result.Add(this.MaterializeCategory(rdr));
}
conn.Close();
}
return result;
}
另外需要MaterializeCategory 方法转换EntityDataReader 为Category 实体对象。
private Category MaterializeCategory(EntityDataReader rdr)
{
Category category = Category.CreateCategory(
rdr.GetInt32(0),
Convert.ToString(rdr[1]),
rdr.GetGuid(2),
DateTime.Now);
return category;
}
下面采用LINQ to Entities 检索全部有ParentCategory的Category 实体。你会注意到,下面的方法不再需要上面的MaterializeCategory方法,对象服务(Object Services)直接从EDM中返回实体对象,代码简化了很多。
var categories = from c in this.context.Category
where c.ParentCategory.Name != null
orderby c.Name
select c;
return categories.ToList();
2. 填充Product Model 下拉列表框
同样采用LINQ to Entities 查询所有的Model 实体。
var models = from m in this.context.Model
orderby m.Name
select m;
return models.ToList();
3. 使用Entity SQL和对象服务(Object Services)检索产品列表
因为Entity SQL 是基于文本的查询字符串,这样可以方便动态创建查询语句。下面的示例代码提供了对Product / Category / Model 的查询过滤,可以传入参数 ObjectParameter。首先,调用ObjectContext 类的CreateQuery<T>方法,返回ObjectQuery<T>对象;然后传入创建的3个ObjectPrameters 参数对象实例。
实际执行查询操作是在我们访问结果集时发生,如调用ToList(), ToArrray() 等等。
public IList<Product> GetProducts(string productName, Category category, Model model)
{
StringBuilder queryString = new StringBuilder("SELECT VALUE prod FROM AdventureWorksLTEntities.Product AS prod ");
queryString.Append("Where prod.ProductCategory.CategoryID=@CategoryId ");
queryString.Append(" AND prod.ProductModel.ModelID=@ModelId ");
var productParameter = new ObjectParameter("ProductName", productName);
var categoryParameter = new ObjectParameter("CategoryId", category.CategoryId);
var modelParameter = new ObjectParameter("ModelId", model.ModelID);
if (!string.IsNullOrEmpty(productName))
{
queryString.Append("AND INDEXOF(@ProductName, prod.Name) > 0 ");
}
queryString.Append("ORDER BY prod.Name");
var products = this.context.CreateQuery<Product>(queryString.ToString());
products.Parameters.Add(productParameter);
products.Parameters.Add(categoryParameter);
products.Parameters.Add(modelParameter);
return products.ToList();
}
4. 删除、更新、增加新产品记录
使用ObjectContext将对Entity Data Model 的更改更新数据库,与通过EntityClient执行Entity SQL 查询不一样,ObjectContext 方法允许你直接增加新的实体、操作实体或删除实体,并最后保存更新到数据库。
删除产品
当SaveChanges 方法调用时,对象服务产生并对数据库执行类似于T-SQL的插入、更新、或删除语句等等。
public void DeleteProduct(Product product)
{
context.DeleteObject(product);
context.SaveChanges();
}
更新产品
UpdateProduct方法是告诉context调用SaveChanges方法,context已经了解每一个对象的状态,知道哪些更改需要传递到数据库。示例代码如下:
public void UpdateProduct()
{
context.SaveChanges();
}
SaveChanges方法对数据库执行有效的调用,仅仅保存更新的、新增的或删除的对象。针对更新的对象而言,仅更新的字段才会传输到数据库。
新增产品
ObjectContext的AddObject方法需要传入新增实体对象的Entity Set名称,在下面的示例代码中,Product实体的Entity Set名称也为Product。
刷新产品
RefreshProduct方法用来更新页面的显示。
public void RefreshProduct(Product product)
{
context.Refresh(RefreshMode.StoreWins, product);
}
Context的Refresh方法允许客户端的更新被数据库对象更新。在调用Refresh方法后,客户端对象的原始值会被数据库值更新,但是当前值可能或不能被数据库值更新,这取决于RefereshMode。StoreWins 模式表示实体集合中的实体对象将被更新与数据库值一致,而ClientWins 表示仅仅客户端的更新才持久化。
示例程序运行界面如下:
范例程序下载(在底部)!
示例代码分析:
1. 填充Product Category 下拉列表框
下面的代码采用Entity SQL,通过Entity Client 访问EDM,返回全部Category 实体集合。
public IList<Category> GetCategories()
{
IList<Category> result = null;
EntityDataReader rdr;
EntityCommand cmd;
string esqlQuery;
using (EntityConnection conn = new EntityConnection("name=AdventureWorksLTEntities"))
{
conn.Open();
esqlQuery = @"SELECT VALUE c FROM AdventureWorksLTEntities.Category AS c";
result = new List<Category>();
cmd = conn.CreateCommand();
cmd.CommandText = esqlQuery;
rdr = cmd.ExecuteReader(CommandBehavior.SequentialAccess);
while (rdr.Read())
{
result.Add(this.MaterializeCategory(rdr));
}
conn.Close();
}
return result;
}
另外需要MaterializeCategory 方法转换EntityDataReader 为Category 实体对象。
private Category MaterializeCategory(EntityDataReader rdr)
{
Category category = Category.CreateCategory(
rdr.GetInt32(0),
Convert.ToString(rdr[1]),
rdr.GetGuid(2),
DateTime.Now);
return category;
}
下面采用LINQ to Entities 检索全部有ParentCategory的Category 实体。你会注意到,下面的方法不再需要上面的MaterializeCategory方法,对象服务(Object Services)直接从EDM中返回实体对象,代码简化了很多。
var categories = from c in this.context.Category
where c.ParentCategory.Name != null
orderby c.Name
select c;
return categories.ToList();
2. 填充Product Model 下拉列表框
同样采用LINQ to Entities 查询所有的Model 实体。
var models = from m in this.context.Model
orderby m.Name
select m;
return models.ToList();
3. 使用Entity SQL和对象服务(Object Services)检索产品列表
因为Entity SQL 是基于文本的查询字符串,这样可以方便动态创建查询语句。下面的示例代码提供了对Product / Category / Model 的查询过滤,可以传入参数 ObjectParameter。首先,调用ObjectContext 类的CreateQuery<T>方法,返回ObjectQuery<T>对象;然后传入创建的3个ObjectPrameters 参数对象实例。
实际执行查询操作是在我们访问结果集时发生,如调用ToList(), ToArrray() 等等。
public IList<Product> GetProducts(string productName, Category category, Model model)
{
StringBuilder queryString = new StringBuilder("SELECT VALUE prod FROM AdventureWorksLTEntities.Product AS prod ");
queryString.Append("Where prod.ProductCategory.CategoryID=@CategoryId ");
queryString.Append(" AND prod.ProductModel.ModelID=@ModelId ");
var productParameter = new ObjectParameter("ProductName", productName);
var categoryParameter = new ObjectParameter("CategoryId", category.CategoryId);
var modelParameter = new ObjectParameter("ModelId", model.ModelID);
if (!string.IsNullOrEmpty(productName))
{
queryString.Append("AND INDEXOF(@ProductName, prod.Name) > 0 ");
}
queryString.Append("ORDER BY prod.Name");
var products = this.context.CreateQuery<Product>(queryString.ToString());
products.Parameters.Add(productParameter);
products.Parameters.Add(categoryParameter);
products.Parameters.Add(modelParameter);
return products.ToList();
}
4. 删除、更新、增加新产品记录
使用ObjectContext将对Entity Data Model 的更改更新数据库,与通过EntityClient执行Entity SQL 查询不一样,ObjectContext 方法允许你直接增加新的实体、操作实体或删除实体,并最后保存更新到数据库。
删除产品
当SaveChanges 方法调用时,对象服务产生并对数据库执行类似于T-SQL的插入、更新、或删除语句等等。
public void DeleteProduct(Product product)
{
context.DeleteObject(product);
context.SaveChanges();
}
更新产品
UpdateProduct方法是告诉context调用SaveChanges方法,context已经了解每一个对象的状态,知道哪些更改需要传递到数据库。示例代码如下:
public void UpdateProduct()
{
context.SaveChanges();
}
SaveChanges方法对数据库执行有效的调用,仅仅保存更新的、新增的或删除的对象。针对更新的对象而言,仅更新的字段才会传输到数据库。
新增产品
ObjectContext的AddObject方法需要传入新增实体对象的Entity Set名称,在下面的示例代码中,Product实体的Entity Set名称也为Product。
刷新产品
RefreshProduct方法用来更新页面的显示。
public void RefreshProduct(Product product)
{
context.Refresh(RefreshMode.StoreWins, product);
}
Context的Refresh方法允许客户端的更新被数据库对象更新。在调用Refresh方法后,客户端对象的原始值会被数据库值更新,但是当前值可能或不能被数据库值更新,这取决于RefereshMode。StoreWins 模式表示实体集合中的实体对象将被更新与数据库值一致,而ClientWins 表示仅仅客户端的更新才持久化。