代码之家  ›  专栏  ›  技术社区  ›  Jeremy Roberts

将Linq重构为Sql

  •  2
  • Jeremy Roberts  · 技术社区  · 17 年前

    有没有办法将linq重构为sql并利用后期评估?有没有办法重用对象初始化器代码?

    我将业务对象持久化到数据库中,并通过单独的linq到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;
    }
    

    样本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;
    }
    

    当我想使用水合器并同时水合相关对象时,示例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接近我想要的结果,但丢失了LINQtoSQL用于执行后期计算的表达式计算。查询中将返回所有字段。更糟糕的是,如果像这样的代码是子关系,则会为每个子关系调用数据库。这在我们的情况下是不能接受的。

    我看过 LinqKit 虽然它似乎可以满足我的需要,但我更喜欢“开箱即用”。

    1 回复  |  直到 17 年前
        1
  •  0
  •   JustLoren    17 年前

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

    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.
    }