繁体   English   中英

将Linq重构为Sql

[英]Refactoring Linq to Sql

有没有一种方法可以将linq重构为sql并利用后期评估的优势? 有没有一种方法可以重用对象初始化代码?

我有一些业务对象,这些对象保留在数据库中,并通过单独的linq to sql层进行混合。

我希望能够重用执行完全相同的操作的多个查询中的代码。 我想重用的查询部分是对象创建部分。 我还想继续利用后期评估的优势(仅从数据库中获取我想要的列。)

下面给出的示例非常简单,其中一些名称已更改为保护无辜者。

样品1

void GetUserById(Guid userId)
{
    IQueryable<LinqLayer.User> x =
        from user in dataContext.Users
        where user.UserID == userId
        select user;

    IQueryable<BusinessLayer.User> y = hydrateUser(x);

    // Acutally execute the query against the database.
    BusinessLayer.User user = y.First();
}

void GetUserByName(string name)
{
    IQueryable<LinqUser> x =
        from user in dataContext.Users
        where user.FirstName == name
        select user;

    IQueryable<User> y = hydrateUser(x);

    // Acutally execute the query against the database.
    User user = y.First();
}

IQueryable<User> hydrateUser(IQueryable<LinqUser> x)
{
    IQueryable<User> y;
        y = from item in x
        select new User
        {
            ID = item.UserID,
            FirstName = item.FirstName,
            MiddleName = item.MiddleName,
            LastName = item.LastName,
        };
    return y;
}

示例1中发生了几件事。在此示例中,我能够利用linq进行sql后期评估。 如果您观看数据库查询,则仅选中的列是我感兴趣的列(在hydrateUser中列为ID,FirstName等)。 很好,因为我可以重用hydrateUser中的代码。

范例2:

IQueryable<User> hydrateUser(IQueryable<LinqUser> x)
{
    IQueryable<User> y;
        y = from item in x
        select new User
        {
            ID = item.UserID,
            FirstName = item.FirstName,
            MiddleName = item.MiddleName,
            LastName = item.LastName,
            ... Big long list of properties
        };
    return y;
}

IQueryable<User> hydrateUserWithPermissions(IQueryable<LinqUser> x)
{
    IQueryable<User> y;
        y = from item in x
        select new User
        {
            ID = item.UserID,
            FirstName = item.FirstName,
            MiddleName = item.MiddleName,
            LastName = item.LastName,
            ... Big long list of properties
            PermissionList = item.Permissions
        };
    return y;
}

当我想使用hydrateUser并且还对相关对象进行水合时,样本2开始下降。 例如,为权限列表充水。 我现在必须剥离一个完整的单独功能来进行额外的保湿。 如果要初始化的属性更多,则不那么理想。

样品3

IQueryable<User> hydratePermissions(IQueryable<LinqUser> x)
{
    IQueryable<User> y;
        y = from item in x
        select new User
        {
            PermissionList = item.Permissions
        };
    return y;
}

IQueryable<User> hydrateUser(IQueryable<LinqUser> x)
{
    IQueryable<User> y;
        y = from item in x
        select new User
        {
            ID = item.UserID,
            FirstName = item.FirstName,
            MiddleName = item.MiddleName,
            LastName = item.LastName,
            ... Big long list of properties
        };
    return y;
}

我想做的是使用示例3这样的代码构建查询。以某种方式尝试利用这两个功能。 并只进行一次数据库访问。 但是,这不起作用。

样品4

User newUpUserFromLinqUser(LinqUser item)
{
    y = new User
        {
            ID = item.UserID,
            FirstName = item.FirstName,
            MiddleName = item.MiddleName,
            LastName = item.LastName,
        };
    return y;
}

示例4与我想要的接近,但是失去了linq to sql用于后期评估的表达式评估。 所有字段都将返回查询。 更糟糕的是,如果像这样的代码是子关系,则每个孩子都会调用数据库。 在我们的情况下,这是不可接受的。

补充笔记

带宽非常宝贵。 我们精确地控制了什么数据,因此查询尽可能精简非常重要。

我看过LinqKit ,虽然它似乎可以满足我的需要,但我还是希望“开箱即用”。

目前,整体架构尚待辩论。

您是否考虑过向用户显式加载Permissions对象?

using (var db = new dbContext())
{
  DataLoadOptions dlo = new DataLoadOptions();
  dlo.LoadWith<LinqUser>(lu => lu.Permissions);
  db.LoadOptions = dlo;
  //Execute code, knowing that when you retrieve users, it will also retrieve their permissions.
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM