C# 关于查找缺少的密钥的查询是否可以改进?(SQL或LINQ)
我正在开发一个ASP.NETMVC网站,并正在寻找一种改进此例程的方法。它可以在LINQ级别或SQL Server级别进行改进。我希望我们最多能在一次查询电话内完成 以下是相关表格和一些示例数据: 我们不限制每个C# 关于查找缺少的密钥的查询是否可以改进?(SQL或LINQ),c#,sql,sql-server,linq,C#,Sql,Sql Server,Linq,我正在开发一个ASP.NETMVC网站,并正在寻找一种改进此例程的方法。它可以在LINQ级别或SQL Server级别进行改进。我希望我们最多能在一次查询电话内完成 以下是相关表格和一些示例数据: 我们不限制每个键都必须有每个LanguageId值,实际上业务逻辑不允许这样的限制。但是,在应用程序级别,我们希望警告管理员某个键缺少某个/某些语言值。所以我有这个类和查询: public class LocalizationKeyWithMissingCodes { public stri
键
都必须有每个LanguageId
值,实际上业务逻辑不允许这样的限制。但是,在应用程序级别,我们希望警告管理员某个键缺少某个/某些语言值。所以我有这个类和查询:
public class LocalizationKeyWithMissingCodes
{
public string Key { get; set; }
public IEnumerable<string> MissingCodes { get; set; }
}
public class LocalizationKeyWithMissingCodes
{
公共字符串密钥{get;set;}
公共IEnumerable缺失代码{get;set;}
}
此方法获取键列表以及任何缺少的代码(例如,如果我们有en+jp+ch语言代码,并且键只有en+ch的值,则列表将包含jp):
public IEnumerable GetAllKeysWithMissingCodes()
{
var languageList=Utils.ResolveDependency().GetActive();
var languageIdList=languageList.Select(q=>q.Id);
var languageIdDictionary=languageList.ToDictionary(q=>q.Id);
var keyList=this.GetActive()
.选择(q=>q.Key)
.Distinct();
var result=新列表();
foreach(键列表中的var键)
{
//获取丢失的代码
var existingCodes=this.Get(q=>q.Active&&q.Key==Key)
.Select(q=>q.LanguageId);
//ToList,以确保在申请时对其进行处理
var missingLangId=languageList.Where(q=>!existingCodes.Contains(q.Id))
.ToList();
结果.添加(新的LocalizationKeyWithMissingCodes()
{
键=键,
MissingCodes=missingLangId
.Select(q=>languageIdDictionary[q.Id].Code),
});
}
result=result.OrderByDescending(q=>q.MissingCodes.Count()>0)
.ThenBy(q=>q.Key)
.ToList();
返回结果;
}
我认为我当前的解决方案不好,因为它会对每个键进行查询调用。有没有一种方法可以改进它,或者使它更快,或者在一个查询调用中打包
编辑:这是答案的最终查询:
public IQueryable<LocalizationKeyWithMissingCodes> GetAllKeysWithMissingCodes()
{
var languageList = Utils.ResolveDependency<ILanguageRepository>().GetActive();
var localizationList = this.GetActive();
return localizationList
.GroupBy(q => q.Key, (key, items) => new LocalizationKeyWithMissingCodes()
{
Key = key,
MissingCodes = languageList
.GroupJoin(
items,
lang => lang.Id,
loc => loc.LanguageId,
(lang, loc) => loc.Any() ? null : lang)
.Where(q => q != null)
.Select(q => q.Code)
}).OrderByDescending(q => q.MissingCodes.Count() > 0) // Show the missing keys on the top
.ThenBy(q => q.Key);
}
public IQueryable GetAllKeysWithMissingCodes()
{
var languageList=Utils.ResolveDependency().GetActive();
var localizationList=this.GetActive();
返回本地化列表
.GroupBy(q=>q.Key,(Key,items)=>newlocalizationkeywithmissingcodes()
{
键=键,
缺失代码=语言列表
.GroupJoin(
项目,
lang=>lang.Id,
loc=>loc.LanguageId,
(lang,loc)=>loc.Any()?null:lang)
.其中(q=>q!=null)
.选择(q=>q.Code)
}).OrderByDescending(q=>q.MissingCodes.Count()>0)//在顶部显示缺少的键
.ThenBy(q=>q.Key);
}
以下是用于识别缺少“完整”语言分配的键的SQL逻辑:
SELECT
all.[Key],
all.LanguageId
FROM
(
SELECT
loc.[Key],
lang.LanguageId
FROM
Language lang
FULL OUTER JOIN
Localization loc
ON (1 = 1)
WHERE
lang.Active = 1
) all
LEFT JOIN
Localization loc
ON (loc.[Key] = all.[Key])
AND (loc.LanguageId = all.LanguageId)
WHERE
loc.[Key] IS NULL;
要查看所有关键点(而不是筛选),请执行以下操作:
以下是用于识别缺少“完整”语言分配的键的SQL逻辑:
SELECT
all.[Key],
all.LanguageId
FROM
(
SELECT
loc.[Key],
lang.LanguageId
FROM
Language lang
FULL OUTER JOIN
Localization loc
ON (1 = 1)
WHERE
lang.Active = 1
) all
LEFT JOIN
Localization loc
ON (loc.[Key] = all.[Key])
AND (loc.LanguageId = all.LanguageId)
WHERE
loc.[Key] IS NULL;
要查看所有关键点(而不是筛选),请执行以下操作:
您的代码似乎在进行大量的数据库查询和具体化 就LINQ而言,单个查询如下 我们使用语言和本地化表的笛卡尔积来获得(键,代码)的所有组合,然后减去关系中存在的(键,代码)元组。这为我们提供了不存在的(键、代码)组合
var result = context.Languages.Join(context.Localizations, lang => true,
loc => true, (lang, loc) => new { Key = loc.Key, Code = lang.Code })
.Except(context.Languages.Join(context.Localizations, lang => lang.Id,
loc => loc.LanguageId, (lang, loc) => new { Key = loc.Key, Code = lang.Code }))
.GroupBy(r => r.Key).Select(r => new LocalizationKeyWithMissingCodes
{
Key = r.Key,
MissingCodes = r.Select(kc => kc.Code).ToList()
})
.ToList()
.OrderByDescending(lkmc => lkmc.MissingCodes.Count())
.ThenBy(lkmc => lkmc.Key).ToList();
p、 我在移动中输入了这个LINQ查询,所以如果它有语法问题,请告诉我。。
查询的要点是,我们采用笛卡尔积并减去匹配行 您的代码似乎在进行大量的数据库查询和具体化 就LINQ而言,单个查询如下 我们使用语言和本地化表的笛卡尔积来获得(键,代码)的所有组合,然后减去关系中存在的(键,代码)元组。这为我们提供了不存在的(键、代码)组合
var result = context.Languages.Join(context.Localizations, lang => true,
loc => true, (lang, loc) => new { Key = loc.Key, Code = lang.Code })
.Except(context.Languages.Join(context.Localizations, lang => lang.Id,
loc => loc.LanguageId, (lang, loc) => new { Key = loc.Key, Code = lang.Code }))
.GroupBy(r => r.Key).Select(r => new LocalizationKeyWithMissingCodes
{
Key = r.Key,
MissingCodes = r.Select(kc => kc.Code).ToList()
})
.ToList()
.OrderByDescending(lkmc => lkmc.MissingCodes.Count())
.ThenBy(lkmc => lkmc.Key).ToList();
p、 我在移动中输入了这个LINQ查询,所以如果它有语法问题,请告诉我。。
查询的要点是,我们采用笛卡尔积并减去匹配行 另一种可能性,使用LINQ:
public IEnumerable<LocalizationKeyWithMissingCodes> GetAllKeysWithMissingCodes(
List<Language> languages,
List<Localization> localizations)
{
return localizations
.GroupBy(x => x.Key, (key, items) => new LocalizationKeyWithMissingCodes
{
Key = key,
MissingCodes = languages
.GroupJoin( // check if there is one or more match for each language
items,
x => x.Id,
y => y.LanguageId,
(x, ys) => ys.Any() ? null : x)
.Where(x => x != null) // eliminate all languages with a match
.Select(x => x.Code) // grab the code
})
.Where(x => x.MissingCodes.Any()); // eliminate all complete keys
}
public IEnumerable GetAllKeysWithMissingCodes(
列出语言,
列表(本地化)
{
返回本地化
.GroupBy(x=>x.Key,(Key,items)=>newLocalizationKeywithMissingCodes
{
键=键,
丢失代码=语言
.GroupJoin(//检查每种语言是否有一个或多个匹配项
项目,
x=>x.Id,
y=>y.LanguageId,
(x,ys)=>ys.Any()?null:x)
.Where(x=>x!=null)//使用匹配项消除所有语言
.Select(x=>x.Code)//获取代码
})
.Where(x=>x.MissingCodes.Any());//消除所有完整的键
}
另一种可能性,使用LINQ:
public IEnumerable<LocalizationKeyWithMissingCodes> GetAllKeysWithMissingCodes(
List<Language> languages,
List<Localization> localizations)
{
return localizations
.GroupBy(x => x.Key, (key, items) => new LocalizationKeyWithMissingCodes
{
Key = key,
MissingCodes = languages
.GroupJoin( // check if there is one or more match for each language
items,
x => x.Id,
y => y.LanguageId,
(x, ys) => ys.Any() ? null : x)
.Where(x => x != null) // eliminate all languages with a match
.Select(x => x.Code) // grab the code
})
.Where(x => x.MissingCodes.Any()); // eliminate all complete keys
}
public IEnumerable GetAllKeysWithMissingCodes(
列出语言,
列表(本地化)
{
返回本地化
.GroupBy(x=>x.Key,(Key,items)=>newLocalizationKeywithMissingCodes
{
键=键,
丢失代码=语言
.GroupJoin(//检查每种语言是否有一个或多个匹配项
项目,
x=>x.Id,
y=>y.LanguageId,
(x,ys)=>ys.Any()?null:x)
.其中(x=>x!=nul