1

我使用 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 的方法。

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

提前致谢。

4

1 回答 1

2
  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:希望这还不算晚))

于 2018-04-17T06:36:51.993 回答