首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >要排除重写值的LINQ查询?

要排除重写值的LINQ查询?
EN

Stack Overflow用户
提问于 2014-04-30 18:01:11
回答 4查看 485关注 0票数 0

我有以下几张表:

ImageSettingOverrides

TechniqueSettings

SettingKeyValues

来自TechniqueSettings表:

BAZ-FOO设置(SettingKeyId: 7)是对BAZ-Default (SettingKeyId: 4)设置的重写。

按覆盖值分组的查询的预期返回的示例:

我希望编译一个SettingKeyValues给定技术BAZ的列表,并覆盖FOO,该列表排除了重写的BAZ-Default设置,并包含非重写的BAZ-Default设置。

我现在有一个LINQ查询,它根据默认值/重写值对设置键值进行分组:

代码语言:javascript
运行
复制
var techniqueSettings = _dataRepository.All<TechniqueSetting>()
   .Where(s => s.Technique.Equals(TechniqueName, StringComparison.InvariantCultureIgnoreCase))
   // group settings by: e.g. Default | FOO
   .GroupBy(s => s.Override);

从这里,我确定用户是在查询默认值,还是只查询带有重写的默认值:

代码语言:javascript
运行
复制
 var techniqueGroups = techniqueSettings.ToArray();
 if (OverridesName.Equals("Default", StringComparison.InvariantCultureIgnoreCase)) {
    // get the default group and return as queryable
    techniqueSettings = techniqueGroups
       .Where(grp => grp.Key.Equals("Default", StringComparison.InvariantCultureIgnoreCase))
       .AsQueryable();
 } else {
    // get the overrides group - IGrouping<string, TechniqueSetting>
    var overridesGroup = techniqueGroups
       .Where(grp => !grp.Key.Equals("Default", StringComparison.InvariantCultureIgnoreCase))
       .First();

    var defaultGroup = techniqueGroups
       .Where(grp => grp.Key.Equals("Default", StringComparison.InvariantCultureIgnoreCase))
       // we know what is in the overrides, so exlude them from being selected here
       // how to exlude overridden defaults???
       .First();
 }

此外,我情不自禁地认为必须有一个使用JOIN (可能?)的更简单、不那么笨拙的LINQ查询。

注:使用EntityFramework 6.x

__

更新:我发现似乎简化了一些Aggregate,但仍然需要一个匿名方法。

代码语言:javascript
运行
复制
var defaultGroup = techniqueGroups
   .Where(grp => grp.Key.Equals("Default", StringComparison.InvariantCultureIgnoreCase))
   .Aggregate(overridesGroup,
      (overrides, defaults) => {
         var settings = new List<TechniqueSetting>();
         foreach (var setting in defaults) {
            if (overrides.Any(o => o.SettingKey.Key == setting.SettingKey.Key)) {
               continue;
            }

            settings.Add(setting);

         }

         return settings.GroupBy(s => s.Override).First();
      },
      setting => setting);

根据@MarkoDevcic的评论,我还没有试过Join

在这个查询中可以使用Except吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-05-01 14:41:36

我发现Aggregate似乎有点简化,但仍然需要一个匿名方法。

代码语言:javascript
运行
复制
var defaultGroup = techniqueGroups
   .Where(grp => grp.Key.Equals("Default", StringComparison.InvariantCultureIgnoreCase))
   .Aggregate(overridesGroup,
      (overrides, defaults) => {
         var settings = new List<TechniqueSetting>();
         foreach (var setting in defaults) {
            if (overrides.Any(o => o.SettingKey.Key == setting.SettingKey.Key)) {
               continue;
            }

            settings.Add(setting);

         }

         return settings.GroupBy(s => s.Override).First();
      },
      setting => setting);

更新:

我提出了几种扩展方法,允许排除项以及比较和替换:

代码语言:javascript
运行
复制
  internal static IEnumerable<TSource> Exclude<TSource>(this IEnumerable<TSource> Source, Func<TSource, bool> Selector) {
     foreach (var item in Source) {
        if (!Selector(item)) {
           yield return item;
        }
     }
  }  

  internal static IEnumerable<TResult> ReplaceWith<TSource1, TSource2, TResult>(this IEnumerable<TSource1> Source1,
     Func<TSource1, TResult> Source1Result,
     IEnumerable<TSource2> Source2,
     Func<TSource1, IEnumerable<TSource2>, TResult> Selector) {

     foreach (var item in Source1) {
        var replaceWith = Selector(item, Source2);

        if (replaceWith == null) {
           yield return Source1Result(item);
           continue;
        }

        yield return replaceWith;
     }
  }

Exclude相当简单。对于ReplaceWith的使用:

代码语言:javascript
运行
复制
     var settings = _repository.Settings
        .ReplaceWith(s => s.SettingKeyValue,
           _repository.SettingOverrides.Where(o => o.OverrideName == overrideName),
           (s, overrides) => overrides.Where(o => o.Setting == s)
              .Select(o => o.SettingKeyValueOverride)
              .FirstOrDefault())
        .ToList();
票数 0
EN

Stack Overflow用户

发布于 2014-05-05 19:24:28

修正后的答案

值为

int myImageId = 1;

字符串myOverride = "FOO";

字符串myTechnique = "BAZ";

结果=

ImageId覆盖值

1 FOO 1000

值为

int myImageId = 1;

字符串myOverride =“默认”;

字符串myTechnique = "BAZ";

结果=

ImageId覆盖值

1默认10000

代码语言:javascript
运行
复制
    void Main()
    {

        // Create Tables and Initialize values
        // ***********************************
        var techniqueSettings = new List<TechniqueSettings>();
        techniqueSettings.Add(new TechniqueSettings { Id = 1, Override = "Default", SettingKeyId = 3, Technique="BAZ"});
        techniqueSettings.Add(new TechniqueSettings { Id = 2, Override = "Default", SettingKeyId = 4, Technique="BAZ"});
        techniqueSettings.Add(new TechniqueSettings { Id = 3, Override = "FOO", SettingKeyId = 7, Technique="BAZ"});
        techniqueSettings.Add(new TechniqueSettings { Id = 4, Override = "FOO", SettingKeyId = 8, Technique="BAZ"});    

        var imageSettingOverrides = new List<ImageSettingOverrides>();
        imageSettingOverrides.Add(new ImageSettingOverrides {SettingId = 1, ImageId=1, Override=null } );
        imageSettingOverrides.Add(new ImageSettingOverrides {SettingId = 2, ImageId=1, Override="FOO" } );
        imageSettingOverrides.Add(new ImageSettingOverrides {SettingId = 3, ImageId=1, Override="FOO" } );

        var settingKeyValues = new List<SettingKeyValues>();
        settingKeyValues.Add(new SettingKeyValues {Id = 4, Setting="Wait", Value=1000 } );
        settingKeyValues.Add(new SettingKeyValues {Id = 7, Setting="Wait", Value=10000 } );


        int myImageId = 1;
        string myOverride = "FOO";
        string myTechnique = "BAZ";

        var results = from iso in imageSettingOverrides
                join ts in techniqueSettings on iso.SettingId equals ts.Id
                join skv in settingKeyValues on ts.SettingKeyId equals skv.Id
                where iso.ImageId == myImageId &&
                    //iso.Override.Equals(myOverride,StringComparison.InvariantCultureIgnoreCase)  &&
                    ts.Override.Equals(myOverride,StringComparison.InvariantCultureIgnoreCase)  &&
                    ts.Technique.Equals(myTechnique, StringComparison.InvariantCultureIgnoreCase) 
                select new {
                    ImageId = iso.ImageId,
                    Override = ts.Override,
                    Value = skv.Value
                };


        results.Dump();
    }

    // Define other methods and classes here
    public class ImageSettingOverrides
    {
        public int SettingId {get; set;}
        public int ImageId {get; set;}
        public string Override {get; set;}
    }

    public class TechniqueSettings
    {
        public int Id {get; set;}
        public string Override {get; set;}
        public int SettingKeyId {get; set;}
        public string Technique { get; set;}
    }

    public class SettingKeyValues
    {
        public int Id {get; set;}
        public String Setting {get; set;}
        public int Value {get; set;}
    }
票数 0
EN

Stack Overflow用户

发布于 2014-05-08 02:59:39

我要做一些假设。

  1. 如果存在ImageSettingOverrides,则重写还必须匹配在AKA中传递的覆盖(这是join子句中的iSettingsOverrides => iSettingsOverrides.Override == OverridesName )。
  2. 您只需要一个独立的SettingKeyValues列表
  3. TechniqueSetting.Id是键,ImageSettingOverride.TechniqueSettingsId是外键,这就是它们之间的关系。
  4. SettingKeyValue.Id是键,TechniqueSetting.SettingKeyId是外键,这就是它们之间的关系。
  5. 您没有导航属性,我必须进行连接。

如果我了解您的类以及它们之间的关系,这将给出一个SettingKeyValues列表。因为一切都保持IQueryable,所以它应该在服务器上执行。

代码语言:javascript
运行
复制
//I'm assuming these are your variables for each IQueryable
IQueryable<TechniqueSetting> techniqueSettings;
IQueryable<ImageSettingOverride> imageSettingOverrides;
IQueryable<SettingKeyValue> settingKeyValues;

var OverridesName = "FOO";
var TechniqueName = "BAZ";

IQueryable<TechniqueSetting> tSettings;
if (OverridesName.Equals("Default", StringComparison.InvariantCultureIgnoreCase))
{
    // Get a list of TechniqueSettings that have this name and are default
    tSettings = techniqueSettings.Where(t => t.Override == OverridesName && t.Technique == TechniqueName);
}
else
{
    // Get a list of TechniqueSettings Id that are overridden 
    //  The ImageSettingOverrides have the same override 
    var overriddenIDs = techniqueSettings.Where(t => t.Technique == TechniqueName && t.Override == "Default")
                                         .Join(
                                             imageSettingOverrides.Where(
                                                 iSettingsOverrides =>
                                                 iSettingsOverrides.Override == OverridesName),
                                             tSetting => tSetting.SettingKeyId,
                                             iSettings => iSettings.TechniqueSettingsId,
                                             (tSetting, iSettingsOverrides) => tSetting.Id);

    // Get a list of techniqueSettings that match the override and TechniqueName but are not part of the overriden IDs
    tSettings =
        techniqueSettings.Where(
            t =>
            t.Technique == TechniqueName && !overriddenIDs.Contains(t.Id) &&
            (t.Override == OverridesName || t.Override == "Default"));
}

// From expected results seems you just want techniqueSettings and that's what would be in techniqueSettings right now.
// If you want a list of SettingKeyValues (which is what is stated in the questions we just need to join them in now)
var settings = tSettings.Join(settingKeyValues, tSetting => tSetting.SettingKeyId,
                              sKeyValues => sKeyValues.Id, (tSetting, sKeyValues) => sKeyValues)
                        .Distinct();
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23395011

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档