【问题标题】:Automating query mapping with multiple joins via Linq2Db通过 Linq2Db 使用多个连接自动执行查询映射
【发布时间】:2018-02-01 12:47:54
【问题描述】:

我使用 BLToolkit 已经有一段时间了,最​​近我一直在按照作者的建议测试 Linq2Db。

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

让我们从一个简化的例子开始。

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();
}

现在我想要实现的目标以及到目前为止我尝试过的目标:

第一步:自动查询

我想以某种方式将查询“嵌入”到类的元数据中,例如:

选项 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 处理这些对象

这对我来说是科幻小说的起点,因为我不知道如何处理这个问题。

显然,如果我执行:

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

linq2sql 执行完整的选择查询,然后将 Where 应用于已映射的对象。这是我无法承受的真正的性能痛苦。

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

你对我在第一步暴露的内容有何看法?关于第二步选择什么方向有什么建议吗?

提前致谢。

【问题讨论】:

    标签: c# join mapping linq2db


    【解决方案1】:
    1. 您应该在数据库中设置了正确的外键;
    2. 在初始化时使用这个

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

      当您有类似 Foreign 的不是一行,而是多个,例如结果列表时,您需要这个。例如,一个用户可以有一个密码,但访问表中有多个关系。在您的示例中,您不需要这个。

    3. 在来自 linq 的查询中使用 LoadWith(x=>x.constraint),取决于您如何命名它...

    这里是你的问题的一个例子:

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

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

    PS:希望还不算太晚))

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-22
      • 2017-01-27
      • 2018-12-02
      • 1970-01-01
      • 1970-01-01
      • 2019-07-28
      相关资源
      最近更新 更多