1.Join(),两表不必含有外键关系,需要代码手动指定连接外键相等(具有可拓展性,除了值相等,还能指定是>,<以及其他对两表的相应键的关系),以及结果字段。
重载方式(是扩展方法,第一个参数带this,代表自身):
1.public static IQueryable<TResult> Join<TOuter, TInner, TKey, TResult>(this IQueryable<TOuter> outer, IEnumerable<TInner> inner, Expression<Func<TOuter, TKey>> outerKeySelector, Expression<Func<TInner, TKey>> innerKeySelector, Expression<Func<TOuter, TInner, TResult>> resultSelector);
2.public static IQueryable<TResult> Join<TOuter, TInner, TKey, TResult>(this IQueryable<TOuter> outer, IEnumerable<TInner> inner, Expression<Func<TOuter, TKey>> outerKeySelector, Expression<Func<TInner, TKey>> innerKeySelector, Expression<Func<TOuter, TInner, TResult>> resultSelector, IEqualityComparer<TKey> comparer);
2.Include(),两表必须含有外键关系,只需要指定键名对应的类属性名即可,不需指定结果字段(即全部映射)。默认搜索某表时,不会顺带查询外键表,直到真正使用时才会再读取数据库查询;若是使用 Include(),则会在读取本表时把指定的外键表信息也读出来。
/位于namespace System.Data.Entity.Infrastructure
public DbQuery<TResult> Include(string path);
//位于namespace System.Data.Entity,务必引入才能找到该方法。否则只看到上个方法
public static IQueryable<T> Include<T, TProperty>(this IQueryable<T> source, Expression<Func<T, TProperty>> path) where T : class;
public static IQueryable<T> Include<T>(this IQueryable<T> source, string path) where T : class;
主从表结构设计中,如果我们直接以嵌套结构输出主表与从表数据。
每次外层的foreach循环每一次去取出订单时会执行单次的SQL查询,而内层foreach循环的每一笔明细同样会再执行一次查询,从而形成大量的数据库往返查询操作。可以采用EF提供的Incluede方法,将需要的数据一次性取出,避免频繁的查询操作。
using (var context = new KTStoreModel()) {
context.Database.Log = Console.Write;
var customer = context.Customers.
Include("Orders.OrderDetails").
Include("Orders.OrderDetails.Product").
Where(c=>c.Id<5) ;
foreach(var c in customer)
{
Console.WriteLine(c.ContactName);
foreach (var o in c.Orders)
{
Console.WriteLine("\tOrder_Id:{0}",o.Id);
foreach (var od in o.OrderDetails)
{
Console.WriteLine("\t\tProduct_Id:{0}\t{1}\tPrice:{2}",
od.ProductId, od.Product.Name, od.Price);
}
}
}
Console.WriteLine("done");
}
调用Include会完整地载入关联数据,进一步的影响程序的执行运算,因此我们必须小心避免载入完整的关联数据,另外,也可以尝试通过异步的方式进行数据的加载操作,如此一来数据的加载操作就不会影响主程序的执行。
await context.Orders.Include("Customer").ForEachAsync(o =>
{
Console.WriteLine("{0}-{1}", o.Id, o.Customer.ContactName);
foreach (var od in o.OrderDetails)
{
Console.WriteLine("\t{0}", od.Product.Name);
}
});