随笔 - 290  文章 - 10  评论 - 85  2

最近用EntityFramework 4.1把Petshop4.0做了改写.替换掉Model和DAL层.

用的是Update Model From Database, 把碰到的问题列出来备忘:

1. 用Partial Class 把类分开,在db有对应字段的放在EDMX文件里;例如订单总额这种统计数据就放到单独的cs文件.

2. EF自带有缓冲,如果get By Primary Key的记录,用这样的写法会快些

 

            using (var ctx = new MSPetShop4Entities())
            {
                EntityKey key 
= new EntityKey("MSPetShop4Entities.Categories""CategoryId", categoryId);
                
return ctx.GetObjectByKey(key) as Category;
            }
 3. EF 默认打开LazyLoad, 所以要使用关联对象例如Order和LineItem,在linq就要加上Include(xxx),
也可以写成.Include(t => t.LineItems) 这个写法要EF4.1才支持,
并要引用C:\Program Files\Microsoft ADO.NET Entity Framework 4.1\Binaries\EntityFramework.dll

 

using (var ctx = new MSPetShop4OrdersEntities())
            {
                
return ctx.Orders.Include("LineItems").Where(t => t.OrderId.Equals(orderId)).FirstOrDefault();
            }

 4.如何直接写sql?

    ObjectContext.ExecuteStoreCommand(...)和 ObjectContext.ExecuteStoreQuery<T>(...)。
    从函数名不难知道,前者是为了执行某一并无返回集的SQL 命令,例如UPDATE,DELETE操作;
    后者是执行某一个查询,并可以将返回集转换为某一对象(这个对象必须是EDMX文件里面定义的)

    如果是自己定义的view或class,就得用linq自己转换了.

 

                var qry = from t in ctx.Accounts.Include("Profiles")
                          
where t.Profile.Username.Equals(userName) && t.Profile.ApplicationName.Equals(appName)
                          select 
new AddressInfo()
                          {
                              Email 
= t.Email,
                              FirstName 
= t.FirstName,
                              LastName 
= t.LastName,
                              Address1 
= t.Address1,
                              Address2 
= t.Address2,
                              City 
= t.City,
                              State 
= t.State,
                              Zip 
= t.Zip,
                              Country 
= t.Country,
                              Phone 
= t.Phone
                          };

 

 5. 如果db没有定义primary key,保存记录时就会出现错误

     Unable to update the EntitySet 'Cart' because it has a DefiningQuery and no <InsertFunction> element
     exists in the <ModificationFunctionMapping> element to support the current operation     
    解决办法如下:

     http://stackoverflow.com/questions/1589166/it-has-a-definingquery-but-no-insertfunction-element-err

 6. 如何跨数据库访问.

    先在其中一个数据库添加"同义词" synonym, 然后再新建一个View包含该synonym, 再在EDMX文件里定义该View.

 7.EF4.1新的API,DbSet<>.Find()

 

过去我们常常用Where或First(FirstOrDefault)方法来查找对应的实体,比如:

var people = from p in context.People
             
where p.Name.StartsWith("M")
             select u;

var people = context.People.FirstOrDefault(p => p.Name == "Michael");  

这样查找的缺点是:即使我们相应的实体已经被ObjectContext缓存,EF还是会去执行数据库访问,而数据库访问是被普遍认为比较耗费性能的。

 

EF4.1为我们提供了一个新的API: DbSet<>.Find()。它可以帮助我们通过主键来查找对应的实体。并且如果相应的实体已经被ObjectContext缓存,EF会在缓存中直接返回对应的实体,而不会执行数据库访问。

 

比如我们查找主键PersonID为1的Person实体:

var person = context.People.Find(1);

 

也可用于联合主键(比如查找主键PersonID=1, PersonName="Michael"的实体):

 

var person = context.People.Find(1"Michael");

 

注意:此处输入联合主键的次序需要按照我们定义改实体类时声明主键的次序。

 

和之前直接用Where或First的调用不同,Find函数对于刚刚新增的实体也能找到:

 

using (var context = new MyContext())
{
    context.People.Add(
new People { PersonID = 100 });
    var newPerson 
= context.People.Find(100);
}

 

8. CodeFirst 的基类是DbContext, 和DB First/Model First 用的ObjectContext 区别比较大

 

 

9 EF 实用Tips http://www.cnblogs.com/lsxqw2004/category/266012.html

posted on 2011-07-13 11:16  Gu  阅读(...)  评论(...编辑  收藏