【问题标题】:Replace part of a LINQ to SQL query with a reusable method用可重用的方法替换部分 LINQ to SQL 查询
【发布时间】:2017-04-07 07:09:08
【问题描述】:

我们在应用程序中引入了一项新功能,该功能会影响数百个查询。我们必须设置一个bool 字段来指示许可证是否有效,以非常复杂的方式。

我想创建一个方法来返回这个bool 值,并且我想在每个查询中使用它。问题是,如果我按如下所示的方式使用它,它会对每个结果执行单独的查询。

如何使用Expression 将其编译为 SQL 并作为单个查询执行?

原始查询,需要改进

IQueryable<DeviceMinimal> devices = 
    from device in db.Devices
    where device.AccountId = accountId

    select new DeviceMinimal
    {
        Id = device.Id,
        Name = device.Name,
        LicenseIsValid = !checkForLicense || 
            device.License != null && (
                !device.License.TrialStarted
                // && 12+ licensing rules
            )
    };

checkForLicense 是一个bool,表示不需要检查许可证。在某些情况下使用,需要考虑。

解决问题的代码,但会为每个设备引发单独的查询

IQueryable<DeviceMinimal> devices = 
    from device in db.Devices
    where device.AccountId = accountId

    select new DeviceMinimal
    {
        Id = device.Id,
        Name = device.Name,
        LicenseIsValid = 
            LicenseHelper.IsLicenseValid(checkForLicense).Invoke(device)
    };

上面查询中使用的方法:

public static Func<Device, bool> IsLicenseEnabledAndValid(bool checkForLicense)
{
    return result => !checkForLicense ||                 
        result.License != null && (
            !result.License.TrialStarted
            // && 12+ licensing rules
        );
}

【问题讨论】:

    标签: c# linq linq-to-sql


    【解决方案1】:

    如果在查询之前设置DataContextDataLoadOptions 并正确设置它们,则应避免子选择。类似的东西:

    db.LoadOptions.LoadWith<Devices>(p => p.License);
    

    Tha 是默认行为(实体的延迟加载)。您可以通过搜索“linq to sql eagerloading”获得更多信息

    【讨论】:

    • 我理解你的建议,但这与我的问题无关。即使我在 LINQ 查询中使用 Entity.Entity.Entity,它仍然会执行单个 SQL 查询。
    【解决方案2】:

    不确定它是否有效,但您是否尝试在主查询中访问许可证? 换句话说,类似:

    Queryable<DeviceMinimal> devices =
       from device in db.Devices
       where device.AccountId = accountId
    
       select new DeviceMinimal
       {
           Id = device.Id,
           Name = device.Name,
           LicenseIsValid =
            LicenseHelper.IsLicenseEnabledAndValid(checkForLicense).Invoke(device.Licence)
       };
    
    public static Func<License, bool> IsLicenseEnabledAndValid(bool checkForLicense)
    {
        return result => !checkForLicense ||
            result != null && (
           !result.TrialStarted
            // && 12+ licensing rules
          );
    }
    

    如果您需要在您的方法中同时访问设备和许可证,您可能需要将功能更改为类似

    public static Func<Device, License, bool> IsLicenseEnabledAndValid(bool checkForLicense)
    {
       return (device, licence) =>  
      ...
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-06
      相关资源
      最近更新 更多