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()上做判断了。
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));
或者