通过Linq2Db自动化多个连接的查询映射

时间:2017-08-23 19:35:01

标签: c# join mapping linq2db

我已经使用BLToolkit一段时间了,最​​近我一直在测试Linq2Db,正如作者所建议的那样。

我已经能够重新创建我为BLToolkit所做的大部分自动化,但是我正在努力创建一个标准结构来查询具有多个表连接和列子集的数据。实际上,我们使用的当前方法非常简单,我试图获得更自动化的东西,使我们能够在客户端上使用linq2db框架提供的LINQ服务。

让我们开始使用简化示例。

Table HEADER
    Column ID
    Column Name

Table LINE
    Column ID
    Column Header_Id
    Column Element_Id

Table ELEMENT
    Column ID
    Column Name

有了这些表,我成功地生成了POCO类并单独进行了查询并填充了Linq2Db的关联。现在我假装的是查询这样的东西:

SELECT 
    H.ID AS Header_Id, 
    H.Name AS Header_Name,
    L.ID AS Line_Id
    E.ID AS Element_Id
    E.Name AS Element_Name
FROM HEADER H JOIN LINE L ON H.ID = L.Header_Id 
              JOIN ELEMENT E ON L.Element_Id = E.ID

鉴于我已经建立了这样一个类:

public class FullOrderData
{
    public int Header_Id { get; set; }
    public string Header_Name { get; set; }
    public int Line_Id { get; set; }
    public int Element_Id { get; set; }
    public string Element_Name { get; set; }
}

我没有问题查询它:

using(var db = new MyTestDb())
{
    var orderData = db.Query<FullOrderData>(selectQuery).ToList();
}

现在我想要实现的目标和迄今为止我尝试过的目标:

第一步:自动化查询

我想以某种方式&#34;嵌入&#34;查询课程&#39;元数据,如:

选项1

[JoinObjectQuery("SELECT ....")]
public class FullOrderData
{
     ....
}

public static class DataConnectionExtensions
{
    public static IEnumerable<T> QueryJoinObject<T>(this DataConnection db)
   {
        //search for JoinObjectQuery attribute and invoke db.Query<T>(joinObjectQueryAttribute.Query)
   }
}

选项2

public interface IJoinObject
{
    string BaseQuery { get; }
}

public class FullOrderData : IJoinObject
{
    public string BaseQuery => "SELECT....";
}

public static class DataConnectionExtensions
{
    public static IEnumerable<T> QueryJoin<T>(this DataConnection db) where T : IJoinObject, new()
   {
        return db.Query<T>(New<T>.Instance().BaseQuery)
   }
}

到目前为止这么好......或者不是这样,因为第一个选项迫使开发人员知道在哪里调用db.Query()以及何时调用db.QueryJoinObject()和第二个强制创建一个额外的虚拟接口并每次创建一个新实例(尽管可以实现缓存)

第二步:Linq to SQL over这些对象

这是我开始科幻小说的地方,因为我不知道如何处理这个问题。

显然,如果我执行:

db.Query<FullOrderData>().Where(x => x.Header_Id == 1).ToList()

linq2sql执行完整选择查询,然后将Where放在已映射的对象上。这是我无法承受的真正的表演痛苦。

所以,我正在寻找一种方法,以某种方式装饰类linq2db可以生成对应linq语句的SQL。

您对我在第一步中所暴露的内容有何看法?关于第二步选择哪个方向的任何建议?

提前致谢。

1 个答案:

答案 0 :(得分:2)

  1. 您应该在数据库中设置正确的外键;
  2. 初始化时使用此

       LinqToDB.Common.Configuration.Linq.AllowMultipleQuery = true;
    

    你需要这个,当你有外国而不是一行,而是多个,比如结果列表。例如,一个用户可以有一个密码,但在访问表中有多个关系。在你的例子中,你不需要这个。

  3. 在来自linq的查询中使用LoadWith(x =&gt; x.constraint),取决于你如何命名...
  4. 以下是您的问题的示例:

    var result = db.Line
    .LoadWith(x=>x.HeaderForeignKey)
    .LoadWith(x=>x.ElementForeignKey)
    .Where(x => x.HeaderForeignKey.Header_Id == 1).ToList()
    

    现在,您将拥有包含元素和标题的行列表,并且只有DB需要的数据,而不会出现这种性能问题。

    PS:希望不会太迟))