AppBoxFuture: Sql存儲的ORM查詢示例

  上篇介紹集成第三方Sql數據庫時未實現如導航屬性、子查詢等功能,經過大半個月的努力作者初步實現了這些功能,基本上能滿足80%-90%查詢需求,特別複雜的查詢可以用原生sql來處理,下面分別示例介紹。

Like/In/NotIn

public async Task<object> Query()
{
    var codes = new string[] { "001", "003" };
    var q = new SqlQuery<Entities.OrderItem>();
    q.Where(t => t.ProductCode.In(codes));
    q.AndWhere(t => t.Product.Name.Contains("Pro"));
    return await q.ToListAsync();
}
Select t."OrderId",t."ProductCode",t."Quantity" From "OrderItem" t Left Join "Product" j1 On j1."Code"=t."ProductCode" Where t."ProductCode" In (@p1,@p2) And j1."Name" Like @p3

分頁查詢

public async Task<object> Query()
{
    var q = new SqlQuery<Entities.OrderItem>();
    q.Where(t => t.Quantity > 0);
    q.OrderBy(t => t.ProductCode);
    q.Skip(2).Take(2);
    var totalRows = await q.CountAsync();
    return await q.ToListAsync();
}
Select Count(*) From "OrderItem" t Where t."Quantity" > @p1

Select t."OrderId",t."ProductCode",t."Quantity" From "OrderItem" t Where t."Quantity" > @p1 Order By t."ProductCode" Offset 2 Limit 2

EntityRef屬性自動Left Join

  適用於實體建模時指定了EntityRef(一對一關係)。

public async Task<object> Query()
{
    var q = new SqlQuery<Entities.Customer>();
    q.Where(t => t.City.Name == "無錫");
    return await q.ToListAsync(t => new { t.Id, t.Name, CityName = t.City.Name });
}
Select t."Id",t."Name",j1."Name" "CityName" From "Customer" t Left Join "City" j1 On j1."Code"=t."CityCode" Where j1."Name" = @p1

手工Join

  適用於實體建模時未指定EntityRef關係。

public async Task<object> Query()
{
    var q = new SqlQuery<Entities.Customer>();
    var j = new SqlQueryJoin<Entities.City>();

    q.LeftJoin(j, (cus, city) => cus.CityCode == city.Code);
    q.Where(j, (cus, city) => city.Name == "無錫");
    return await q.ToListAsync(j, (cus, city) => new { cus.Id, cus.Name, CityName = city.Name });
}
Select t."Id",t."Name",j1."Name" "CityName" From "Customer" t Left Join "City" j1 On j1."Code"=t."CityCode" Where j1."Name" = @p1

GroupBy分組

public async Task<object> Query()
{
    var q = new SqlQuery<Entities.OrderItem>();
    q.GroupBy(t => t.ProductCode)
        .Having(t => DbFuncs.Sum(t.Quantity) > 0);
    return await q.ToListAsync(t => new { t.ProductCode, Amount = DbFuncs.Sum(t.Quantity) });
}
Select t."ProductCode",Sum(t."Quantity") "Amount" From "OrderItem" t Group By t."ProductCode" Having Sum(t."Quantity") > @p1

SubQuery子查詢

public async Task<object> Query()
{
    var q = new SqlQuery<Entities.OrderItem>();
    var s = new SqlQuery<Entities.Product>();

    q.Where(t => t.ProductCode.In(
        s.Where(p => p.Name.Contains("15")).AsSubQuery(p => p.Code)
        ));
    return await q.ToListAsync();
}
Select t."OrderId",t."ProductCode",t."Quantity" From "OrderItem" t Where t."ProductCode" In (Select t1."Code" From "Product" t1 Where t1."Name" Like @p1)

Eager loading預先加載

  適用於SqlQuery.ToSingleAsync()及ToListAsync()。注意以下示例加載EntitySet屬性,會單獨生成Sql,所以不建議ToListAsync()時預先加載EntitySet屬性,更不建議嵌套預先加載EntitySet。

public async Task<object> Query()
{
    var q = new SqlQuery<Entities.Order>();
    q.Include(order => order.Customer)
        .ThenInclude(customer => customer.City)
     .Include(order => order.Items)
        .ThenInclude(item => item.Product);
    return await q.ToSingleAsync();
}
Select t."Id",t."CustomerId",j1."Id" "Customer.Id",j1."Name" "Customer.Name",j1."CityCode" "Customer.CityCode",j1."Phone" "Customer.Phone",j2."Code" "Customer.City.Code",j2."Name" "Customer.City.Name" From "Order" t Left Join "Customer" j1 On j1."Id"=t."CustomerId" Left Join "City" j2 On j2."Code"=j1."CityCode" Limit 1

Select t."OrderId",t."ProductCode",t."Quantity",j1."Code" "Product.Code",j1."Name" "Product.Name",j1."Unit" "Product.Unit" From "OrderItem" t Left Join "Product" j1 On j1."Code"=t."ProductCode" Where t."OrderId" = @p1

暫未實現Explicit loading(顯式加載);
暫不支持Lazy loading(延遲加載)

小結

  GitHub上的運行時已更新可安裝測試,作者下一步重點是實現獨立的不依賴內置存儲的版本,並且實現模型包的導入與導出功能。另一邊碼代碼一邊碼文實屬不易,作者需要您的支持請您多多點贊推薦!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章