1.DataAccessAdapter
用于数据库的交互,填补单个实例,修改数据,调用存储过程,启动事务等。(注意DataAccessAdapter不是线程安全,每一个线程都应该有自己的实例,创建一个实例是非常快的,官网建议为每一次的查询创建一个新的实例)。
- 连接字符串
DataAccessAdapter会自动读取可用的 .config文件中的链接字符串,但是也可以提供一个链接字符串的重载。可以实现为每一次的调用适用不同的链接字符串。
- 查询超时
DataAccessAdapter.CommandTimeOut可以为每个调用设置查询超时时间,默认是30秒。
- 数据库连接控制
当需要使用多个数据库获取数据时可以使用KeepConnectionOpen属性保持数据库一直打开
- 递归保存
DataAccessAdapter支持递归保存,也是默认的保存方式。在设置一个属性关联到实体时,主外键值得同步性就已经完成。例如
myOrder.Customer = myCustomer,如果myCustomer实体不是新的,在保存之后会执行同步,因此标识列和排序列都是同步的
- 获取/删除/保存实体/列表类型/视图类型
DataAccessAdapter对于获取,删除,保存,填充列表类型和视图类型完全支持,并且还直接提供了对持久存储实体的更新、删除。
- 调用存储过程
DataAccessAdapter完全支持调用存储过程
- 事务
DataAccessAdapter支持ADO.NET事务以及基于System.Transactions的事务。如果调用的是已存在的事务,则会直接调用,否则会创建一个新的事务。
2.实体的使用
所有的实体类都派生自CommonEntityBase的中央基类,CommonEntityBase派生自EntityBase2,该类在ORMSupportClasses程序集中
创建一个新的实体实例
eg:CustomerEntity customer=new CustomerEntity()
实例化一个实体后可以将数据保存至数据库。
eg:
customer.Name="Dylan";
DataAccessAdapter adapter=new DataAccessAdapter();
adapter.SaveEntity(customer,true);
- 重新提取和不同步行为
在SaveEntity时如果传的是true表示在执行保存操作之后立即重新获取实体的数据,所以此时数据时最新的且是同步。如果传递是false,表示不同步,在从一个实体属性读取数据之前,必须从数据库中重新获取实体数据。如果在保存后不需要对实体操作,可以不需要传true;
- 序列/标识值重新获取
在SaveEntity之后会自动设置标识列的值,即使未指定重新获取实体,保存后也可以使用标识列的新值。newid()不会别视为序列字段,这些值不会被回读,所以在保存前需要提供这些值。
实例化一个已存在的实体
- 使用主键值
eg:
CustomerEntity customer = new CustomerEntity("CHOPS");
DataAccessAdapter adapter = new DataAccessAdapter();
adapter.FetchEntity(customer);
这样会获取主键为CHOPS的customer信息
-使用LINQ
CustomerEntity customer=null;
var adapter=new DataAccessAdapter();
var metaData=new LinqMetaData(adapter);
customer=metaData.Customer.FirstOrDefault(c=>c.CustomerId=="CHOPS");
-使用关联性实体
通过相关的实体去实例一个实体时,适配器是不支持自动数据加载,所有的数据都必须预先获取。
OrderEntity order = new OrderEntity(10254);
DataAccessAdapter adapter = new DataAccessAdapter(true);
adapter.FetchEntity(order);
order.Customer = adapter.FetchNewEntity<CustomerEntity>(order.GetRelationInfoCustomer());
adapter.CloseConnection();
加载CHOPS客户,订单号为10254的订单。使用先加载出订单再去加载客户实体。DataAccessAdapter实例化时传的参数new标识KeepConnectionOpen为true,所以在最后要CloseConnection。
会存在以下的关系:
- order.CustomerID = Order.Customer.CustomerID
- order.Customer.Orders.Contains(order)
-使用唯一约束的值
实体上可以具有唯一标识,eg:在CustomerEntity实体中定义了CompanyName上有唯一约束
CustomerEntity customer=new CustomerEntity();
DataAccessAdapter adapter = new DataAccessAdapter();
customer.CompanyName = "Chop-suey Chinese";
adapter.FetchEntityUsingUniqueConstraint(customer, customer.ConstructFilterForUCCompanyName());
- 使用Context对象
如果需要获取已存在于内存中的实体,可以使用Context对象。
CustomerEntity customer = (CustomerEntity)myContext.Get(new CustomerEntityFactory(), "CHOPS");
if(customer.IsNew)
{
//not found in context, fetch from database (assumes 'adapter' is a
//DataAccessAdapter instance)
adapter.FetchEntity(customer);
}
如果实体不存在Context对象中,则返回新的实体对象
- 多态提取
使用场景:BoradMember与CompanyCar是多对一的关系,CompanyCar是父类,FamilyCar和SportsCar为子类
CompanyCarEntity car=adapter.FetchNewEntity<CompanyCarEntity>(myBoardMember.GetRelationInfoCompanyCar());
FamilyCarEntity car=adapter.FetchNewEntity<FamilyCarEntity>(myBoardMemeber.GetRelationInfoCompanyCar());
修改一个对象实体
修改一个对象数据有多种方式:
- 在内存中加载一个已存在的实体,更改一个或多个字段(不能是序列字段)并且调用DataAccessAdapter的SaveEntity()方法;
- 创建新的实体,设置主键值(用于过滤),将IsNew属性设置为false,设置一个或多个值并调用DataAccessAdapter的SaveEntity()方法。这不会改变主键的值。
- 通过DataAccessAdapter的UpdateEntitiesDirectly()方法指定主键为过滤器。
- 更改属性值
DataAccessAdapter的SaveEntity()方法将会知道传给它的实体是否是新的,并使用update查询更改数据库的数据,并用insert插入至数据库。update仅保存已更改的字段,没有更改的字段不执行更新
CustomerEntity customer = new CustomerEntity("CHOPS");
DataAccessAdapter adapter = new DataAccessAdapter();
adapter.FetchEntity(customer);
customer.Phone = "(605)555-4321";
adapter.SaveEntity(customer);
先将Customer实体加载至内存中,更改一个字段在保存,因为设置了主键所以可以只改变一个字段并调用SaveEntity();
- 直接在数据库中更新实体
不需要将实体存入缓存中,相对会高效一些
CustomerEntity customer = new CustomerEntity();
customer.CustomerID="CHOPS";
customer.Phone = "(605)555-4321";
customer.IsNew=false;
DataAccessAdapter adapter = new DataAccessAdapter();
adapter.SaveEntity(customer);
必须设置主键,此时update只会更新单个实体,还得标注customer 的isNew是false,此时数据库才是执行update而不是insert;
如果需要保存后需要将实体加载会内存中,SaveEntity()传入true;
- 使用UpdateEntitiesDirectly()
将Product的CategoryId等于3的Discontinued字段设置为false。UpdateEntitiesDirectly() 返回受影响的行数。
RelationPredicateBucket bucket = new RelationPredicateBucket(ProductFields.CategoryId == 3);
ProductEntity updateValuesProduct = new ProductEntity();
updateValuesProduct.Discontinued=true;
DataAccessAdapter adapter = new DataAccessAdapter();
int amountUpdated = adapter.UpdateEntitiesDirectly(updateValuesProduct, bucket);
删除实体
删除实体的几种方式:
将实体加载至内存中再执行DataAccessAdapter.DeleteEntity();
在内存中创建一个新的实例,设置主键值再调用DataAccessAdapter.DeleteEntity()。这种方式避免了将实体存在内存中。
使用DataAccessAdapter.DeleteEntityCollection()方法删除实体集合。
-
使用DataAccessAdapter.DeleteEntitiesDirectly()方法直接从数据库中删除实体。
DataAccessAdapter adapter = new DataAccessAdapter(); CustomerEntity customer = new CustomerEntity("CHOPS"); adapter.DeleteEntity(customer);
删除是不会递归的,如果删除操作违反主外键约束会抛出异常。