再努力一点点

没有烟抽的日子
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Linq to sql 几个需要注意的地方

Posted on 2010-07-15 21:47  ZhangPeng.Chen  阅读(420)  评论(0编辑  收藏  举报

1. RepositoryBase<T> : IQueryable<T>
    大部分同学使用Linq to sql都会自己写一个RepositoryBase<T>,如果继承至IQueryable<T>会让你用的很舒畅。
        比如:
            Repository.GetAll().Count(it=>...) 与 Repository.Count(it=>...)
            你会更喜欢什么呢?当然这也算个人喜好吧。


2. 如何判断实体状态
    如何判断实体是直接New出来的,还是从数据库中Get出来的,由于没有像Entity Framework中的EntityState,Linq to sql要怎么判断呢?
        测试: 
            直接New一个实体,执行OnCreated()
            从数据库中Get一个实体,执行OnLoaded(), OnCreated()
            这样我们就可以在OnLoaded()上做判断了。

public partial class Entity {
    
partial void OnLoaded() {
        IsNew 
= false;
    }

    
private bool _isNew = true;
    
public bool IsNew
    {
        
get { return _isNew; }
        
set { _isNew = value; }
    }
}


3. Lazy load
    3.1 Lazy load给我们带了非常大的方便,不过有时也藏着危险,所以我们在写相关语句的时候也需要留意一下,有没有可以优化的方法。
          比如在循环语句里写Lazy load的时候,就应该考虑会不会每次都发SQL请求呢?
    3.2 this.Product.Categories.Any(it=>it...) 大家想想会发出什么SQL请求呢?

EntitySet<Category> Categories // 是EntitySet<T>

EntitySet<TEntity> : IList, ICollection, IList<TEntity>, ICollection<TEntity>, IEnumerable<TEntity>, IEnumerable, IListSource where TEntity : class // 并没有实现IQueryable

所以会发一条Sql语句,把关联的Category都取出来。然后调用IEnumerable这个集合的Any扩展。
而不是直接发一条关于Any的Sql语句。
  3.3 Lazy load是会缓存的
    user.Role
    user.Role
    user.Role
    // 调用三次,但实践上只会发送一次请求,不要以为Linq to sql很笨。
    

4. 立即加载
    有Lazy load,当然也就有立即加载。
    Linq to sql的立即加载都是使用DataLoadOptions下的LoadWith<T>与AssociateWith<T>,而这个设置必须在DataContext返回数据之前被设置。
    应该会有很多同学和我一样把DataContext放在上下文中,如果是非web请求,就放在CallContext中,这样一个请求下来DataContext就是唯一的。
 
    比如:
        后台一个取产品列表的页面,现在要立即加载分类。
        首先进入该页面,进行用户验证,这已经返回了一次数据, 取产品列表,在DataContext上设置LoadWith<Product>(it=>it.Category)出错了。
       
        所以我们只能把LoadWith<Product>(it=>it.Category)搬到构造DataContext的地方,这样就可以了。
        虽然代码上不直观,不过性能上好像没有什么影响,也没有产生额外的SQL语句,只有在加载Product的时候,会inner join下Category。

    当然当你想取Product不加载Category时,抱歉,没办法了。。。

5. == NULL 并不等价于 is NULL
    5.1
    int? parentId = null;
    Repositoy.Count(it=>it.ParentId == parentId); // == NULL

    5.2
    Repositoy.Count(it=>it.Parent == null); // is NULL
   
    第1条语句结果始终为0。== NULL 不要用切记切记。

   你可以使用
   Repository.Count(it=>object.Equals(it.ParentId, parentId));
   或者  

   Repository.Count(it=>parentId == null ? it.ParentId == null : it.ParentId == parentId);