.net 3.5 数据库开发 之 ADO.net Entity Framework

 

     在LINQ to SQL一节中也讲过关于LINQ to SQL与ADO.net Entity Framework的区别,以及两者分别在什么情况下使用。ADO.net Entity Framework是在LINQ to SQL之后产生的,现在还处在bata3版本中。微软很早就已经在准备设计实现自己的ORM框架,所以有的人认为LINQ to SQL的出现,主要是因为微软ORM框架久久未能实现,所以先做了一个简单的版本,一方面满足用户的需求,另一方面想全面的ORM框架过渡。不论这种说法争取与否,ADO.net Entity Framework在ORM实现框架上的却是比LINQ to SQL更加完善。ADO.net Entity Framework(以后简称AEF)用C(概念层)S(存储层)M(映射层)三层结构实现了ORM中的C(概念层)L(逻辑层)P(数据存储层)三层结构。AEF的三层结构比ORM的三层概念型的结构更加实用。用户可以不用关心SM层(这些可以由Visual Studio设计工具自动生成,当然,如果知道具体细节,则可操作空间会更大),直接对C层进行操作,在C层,系统自动将数据库表中的行映射成为实体对象,和LINQ to SQL类似,数据库对应实体对象名为<数据库名>Entities(在LINQ to SQL中为<数据库名>DataContext),行数据实体类名和对应的表名一致,如数据库中的Order表会对应成Orders实体类,其中表名后是否加s(即对应成Order类还是Orders类)可以在Visual Studio 中设置。

     

     当定义好 Entity Data Model 的 CS/MS/SS 之后,即可以利用 ADO.NET Entity Framework 的用户端来访问 EDM,EDM 中的数据提供者会向数据来源访问数据,再传回用户端。

  从上图可以看出,目前 ADO.NET Entity Framework 有三种用户端:

  Entity Client

  Entity Client 是 ADO.NET Entity Framework 中的本地用户端 (Native Client),它的对象模型和 ADO.NET 的其他用户端非常相似,一样有 Connection, Command, DataReader 等对象,但最大的差异就是,它有自己的 SQL 指令 (Entity SQL),可以用 SQL 的方式访问 EDM,简单的说,就是把 EDM 当成一个实体数据库。

ContractedBlock.gif ExpandedBlockStart.gif 程序5-1
// Initialize the EntityConnectionStringBuilder.
EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder();
//Set the provider name.
entityBuilder.Provider = providerName;
// Set the provider-specific connection string.
entityBuilder.ProviderConnectionString = providerString;
// Set the Metadata location.
entityBuilder.Metadata = @"res://*/AdventureWorksModel.csdl|
res://*/AdventureWorksModel.ssdl|
res://*/AdventureWorksModel.msl
";

Console.WriteLine(entityBuilder.ToString());

using (EntityConnection conn = new EntityConnection(entityBuilder.ToString()))
{
  conn.Open();
  Console.WriteLine(
"Just testing the connection.");
  conn.Close();
}


 

  Object Context

  由于 Entity Client 太过于制式,而且也不太符合 ORM 的精神,因此微软在 Entity Client 的上层加上了一个供编程语言直接访问的界面,它可以把 EDM 当成对象般的访问,此界面即为 Object Context (Object Service)。

  在 Object Context 中对 EDM 的任何动作,都会被自动转换成 Entity SQL 送到 EDM 中执行。

ContractedBlock.gif ExpandedBlockStart.gif 程序5-2
// Get the contacts with the specified name.
ObjectQuery<Contact> contactQuery = context.Contact
                              .Where(
"it.LastName = @ln AND it.FirstName = @fn",
                                   
new ObjectParameter("ln", lastName), 
                                   
new ObjectParameter("fn", firstName));

 

  LINQ to Entities

  Object Context 将 EDM 的访问改变为一种对对象集合的访问方式,这也就让 LINQ 有了发挥的空间,因此 LINQ to Entities 也就由此而生,简单的说,就是利用 LINQ 来访问 EDM,让 LINQ 的功能可以在数据库中发挥。

ContractedBlock.gif ExpandedBlockStart.gif 程序5-3
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
  ObjectQuery
<Product> products = AWEntities.Product;
  IQueryable
<Product> productNames =
                                              from p 
in products
                                              select p;
}

 

Entity SQL

     在介绍Entity Client时,提到了Entity SQL,在这里做一下简单的介绍:

Entity SQL(以后简称ESQL)和传统的SQL十分类似,但仍有些地方不同:

ESQL中没有*(即传统SQL中的SELECT * FROM...),但选择对象的所有属性时,可以使用VALUE,

如: SELECT VALUE c FROM NorthwindEntities.Customers AS c

在FROM区域,ESQL所提取数据的地方是EDM(Entity Data Model),此处必须是一个Entity class,且包含Entity Container名称,如上例所示

下面介绍一下ESQL常用的关键字:

TOP:和SQL类似,如: SELECT VALUE TOP(5) c FROM NorthwindEntities.Customers AS c

SKIPSELECT VALUE c FROM NorthwindEntities.Customers AS c

          ORDER BY c.CustomerID SKIP(5)

          注意:SKIP是放在整个查询表达式之后的,并且,SKIP必须和ORDER BY合用才行

LIMIT: LIMIT用来限制回传结果集的条数,类似与TOP,同样是取结果集的前N条数据,但是LIMIT必须与ORDER BY合用,同样,LIMIT也可以和SKIP合用

          如:SELECT VALUE c FROM NorthwindEntities.Customers AS c

               ORDER BY c.CustomerID SKIP(5) LIMIT(5)

WHERE、LIKE、IN、BETWEEN、GROUP BY、JOIN:都和传统SQL使用方式相同,所以不再特别介绍

像SQL语句一样,ESQL也有很多内置的函数,详细信息可查阅MSDN

 

     ADO.net Entity Framework的使用

     由于ADO.net Entity Framework的基本操作和LINQ to SQL十分类似,所以我们可以参照LINQ to SQL来操作ADO.net Entity Framework。下面主要介绍一下LINQ to SQL和ADO.net Entity Framework在应用中的不同之处

     数据的更新:数据操作不外乎C(Create)R(Receive)U(Update)D(Delete)四个大项,其中R的角色由LINQ Expression执行,LINQ Expression的使用上,LINQ to SQL和AEF基本一样,剩下的CUD则是由DataContext(LINQ to SQL)或Entities(AEF)来执行:

1.Create:LINQ to SQL中采用Entity Object调用InsertOnSubmit方法进行插入,而在AEF中,设计工具会自动在数据库实体类中为每个表添加一个AddTo<Entity class>的方法,如AddToOrders,而这个方法只是一个Proxy,实际是间接调用数据库对象的AddObject方法

LINQ to SQL

ContractedBlock.gifExpandedBlockStart.gif程序5-4

// Create a new Order object.
Order ord = new Order
ExpandedBlockStart.gifContractedBlock.gif
{
    OrderID 
= 12000,
    ShipCity 
= "Seattle",
    OrderDate 
= DateTime.Now
    
// …
}
;

// Add the new object to the Orders collection.
db.Orders.InsertOnSubmit(ord);

// Submit the change to the database.
try
ExpandedBlockStart.gifContractedBlock.gif
{
    db.SubmitChanges();
}

catch (Exception e)
ExpandedBlockStart.gifContractedBlock.gif
{
    Console.WriteLine(e);
    
// Make some adjustments.
    
// 
    
// Try again.
    db.SubmitChanges();
}

 

ADO.net Entity Framework

ContractedBlock.gif ExpandedBlockStart.gif 程序5-5
/// <summary>
/// 插入
/// </summary>
public void Insert()
{
    
using (NorthwindEntities northwind = new NorthwindEntities())
    {
        Orders order 
= Orders.CreateOrders(northwind.Orders.Count(), "Suzhou");
        
// 或 Orders order = new Orders() { OrderID = northwind.Orders.Count() + 1, ShipCountry = "Suzhou" };

        northwind.AddToOrders(order);
        
// 或 northwind.AddObject("Orders", order);

        northwind.SaveChanges();
    }
}

 

2.Delete LINQ to SQL

ContractedBlock.gif ExpandedBlockStart.gif 程序5-6
// Query the database for the rows to be deleted.
var deleteOrderDetails =
    from details 
in db.OrderDetails
    
where details.OrderID == 11000
    select details;

foreach (var detail in deleteOrderDetails)
{
    db.OrderDetails.DeleteOnSubmit(detail);
}

try
{
    db.SubmitChanges();
}
catch (Exception e)
{
    Console.WriteLine(e);
    
// Provide for exceptions.
}

 

ADO.net Entity Framework

ContractedBlock.gif ExpandedBlockStart.gif程序5-7
/// <summary>
/// 删除
/// </summary>
public void Delete()
{
    
using (NorthwindEntities northwind = new NorthwindEntities())
    {
        
int maxID = 3;

        Orders order 
= northwind.Orders.First<Orders>(od => od.OrderID > maxID);

        
if (null == order)
            
return;

        northwind.DeleteObject(order);

        northwind.SaveChanges();

        
// 或
         var orders = from od in northwind.Orders
                     
where od.OrderID > maxID
                     select od;

        
if (null == orders)
            
return;

        
foreach (var orderDel in orders)
        {
            northwind.DeleteObject(orderDel);
        }

        northwind.SaveChanges();
    }
}

 

3.Update LINQ to SQL 和 ADO.net Entity Framework的更新基本一样,所以不再分别列出,下面以AEF为例

ContractedBlock.gif ExpandedBlockStart.gif 程序5-8
ExpandedBlockStart.gifContractedBlock.gif/**//// <summary>
/// 修改
/// </summary>

public void Modify()
ExpandedBlockStart.gifContractedBlock.gif
{
    
using (NorthwindEntities northwind = new NorthwindEntities())
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        Orders order 
= northwind.Orders.First<Orders>(od => od.OrderID > 2);
        
// 或 Orders order = northwind.Orders.Where<Orders>(od => od.OrderID < 5).First();

        
if (null == order)
            
return;

        order.OrderID 
= 3;
          order.OrderDate 
=
 DateTime.Now;
          order.ShipCountry 
= "Suzhou"
;

        northwind.SaveChanges();
   }

}

 

在n-Tier中,有时Client调用了Service(如下面程序5-6中的GetObject方法)来取得对象,如果对象和ObjectContext没有了任何关联,其只是一个一般的对象,在客户端中我们先保存对象的原始值,然后对复制的对象进行修改,修改后通过Serveice(AttachNow)将数据异动回数据库,这时可以采用下例中的方法:

ContractedBlock.gif ExpandedBlockStart.gif 程序5-9
ExpandedBlockStart.gifContractedBlock.gif/**//// <summary>
/// Server:获取对象
/// </summary>

static NorthwindEntities GetObject()
ExpandedBlockStart.gifContractedBlock.gif
{
        Orders order;
        
using (NorthwindEntities northwind = new NorthwindEntities())
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
                order  
= (from o in northwind.Orders
                            
where o.OrderID > 5
                             select o).FirstOrDefault();
                northwind.Detach(order);
        }

        
return order;
}


ExpandedBlockStart.gifContractedBlock.gif
/**//// <summary>
/// Server:将数据异动回数据库
/// </summary>

static void AttachNow(Orders order,  Orders updateItem)
ExpandedBlockStart.gifContractedBlock.gif
{
        NorthwindEntities northwind 
= new NorthwindEntities();
        northwind.Attach(item);        
// 将原始值与northwind建立关系
        northwind.ApplyPropertyChanges("OrderID", updateItem); // 将变动值和原始值配对
        northwind.SaveChanges();        // 更新回数据库
}


ExpandedBlockStart.gifContractedBlock.gif
/**//// <summary>
/// Client:通过Server获取对象并更新,将更新结果异动回数据库
/// </summary>

static void Update()
ExpandedBlockStart.gifContractedBlock.gif
{
        NorthwindEntities.Orders order 
= GetObject();
        NorthwindEntities.Orders updateItem 
= new NorthwindEntities.Orders();
        updateItem.OrderID 
= order.OrderID;
        updateItem.OrderDate 
= order.OrderDate;
        updateItem.OrderDate 
= System.Date.Now;
        AttachNow(order, updateItem);
}

 

转载于:https://www.cnblogs.com/Lucen/archive/2009/03/06/1404597.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值