我们正在使用代码优先实体框架开发一个业务应用程序,我正在寻找解决以下问题的方法,如果可能的话,这个问题不会出现在数据库之外。
我们有一个类似于以下内容的持久性模型:
public abstract class DataCode
{
public long Id { get; set; }
public string Code { get; set; }
public string Description { get; set; }
}
public class Option : DataCode
{
// a bunch of stuff that describes an Option
}
public class Model : DataCode
{
// a bunch of stuff that describes a product model
}
public class Version
{
public long Id { get; set; }
// a bunch of stuff that describes a version of the product model
}
public class ModelOptionVersion
{
public Model ThisModel { get; set; }
public Option WithThisOption { get; set; }
public Version UsingThisVersion { get; set; }
// a bunch of stuff that is important to track
// at the intersection of these three properties
}除了用户希望使用“家庭代码”和“公共代码”来应用属性值之外,所有这些代码都工作得很好。为了支持这一点,我认为以下课程将有效:
public abstract class CodeGroup
{
public virtual ICollection<DataCode> DataCodes { get; set; }
}
public class Family : CodeGroup, DataCode
{
public Family(ICollection<Model> Models)
{
base:DataCodes = Models;
}
}
public class CommonCode : CodeGroup, DataCode
{
public Family(ICollection<Option> Options)
{
base:DataCodes = Options;
}
}这对于将FamilyCode和CommonCode以及一些逻辑扩展到单独的ModelOptionVersion记录(foreach Model in Family...)是很好的,也是很好的。然而,阻碍我的是如何将一组ModelOptionVersion记录最好地匹配到FamilyCode或CommonCode代表中。
如果这是福特(它不是),数据可能如下所示:
Family | Model
Trucks | F-150
Trucks | F-250
Trucks | F-350
SuperDuty | F-250
SuperDuty | F-350
CommonCode | Option
Gas Engines | 4.6l V-8 Gas
Gas Engines | 5.4l V-8 Gas
Diesel Engines | 6.4l V-8 Diesel
Diesel Engines | 7.3l V-8 Diesel
Diesel Engines | 6.0l V-8 Diesel
Model | Option | Version
F-150 | 4.6l V-8 Gas | 2015
F-150 | 4.6l V-8 Gas | 2016
F-150 | 5.4l V-8 Gas | 2015
F-150 | 5.4l V-8 Gas | 2016
F-250 | 5.4l V-8 Gas | 2015
F-250 | 5.4l V-8 Gas | 2016
F-350 | 5.4l V-8 Gas | 2015
F-350 | 5.4l V-8 Gas | 2016
F-250 | 6.4l V-8 Diesel | 2015
F-250 | 6.4l V-8 Diesel | 2016
F-350 | 6.4l V-8 Diesel | 2015
F-350 | 6.4l V-8 Diesel | 2016用户希望根据“超级柴油发动机”或"2016卡车加燃气发动机“对商品进行定价。当他们创造价格记录时,他们不仅希望看到这一点,而且当他们回头再看的时候。因此,我需要一种方法,不仅扩展FamilyCode和DataCode成员,而且将它们卷起来。但从数据中不一定清楚数据的来源是什么。而且,系统应该足够聪明,当有人说“这只在F-250和F-350上可用”时,系统会说“使用SuperDuty”。
在我看来,我需要某种最好的解决方案,也许是一些轻量级的模糊逻辑。是否存在用于此的.NET库?我必须从头开始做吗?我怎样才能做到这一点?
发布于 2015-08-05 21:43:38
然而,阻碍我的是如何将一组ModelOptionVersion记录最好地匹配到FamilyCode或CommonCode代表中。
您在这里要做的是找到FamilyCodes (或CommonCodes),以便某个集合中的每个ModelOptionVersion都有一个由该FamilyCode指定的模型。
var desiredModels = // some collection of Models
var familyCodesByFamily = (
from familyCode in db.FamilyCodes
group familyCode by familyCode.Family into family
select family);
var applicableFamilies = (
from family in familyCodesByFamily
where desiredModels.All(dm => family.Any(f=> f.Model == dm))
select family.Key).ToList();我还没有测量这种查询的性能,但它并不能很直接地映射到SQL能做什么。SQL并不直接允许您执行通用量词(“给我x,y"),但它允许您做存在量词(”给我x,这样就有y")和否定。如果发现上述方法效果不佳,则在语义上应该等效的另一种公式是:
var incorrectFamilies =
(from familyCode in db.FamilyCodes
where !desiredModels.Contains(familyCode.Model)
select familyCode.Family).Distinct();
var correctFamilies =
(from familyCode in db.FamilyCodes
where !incorrectFamilies.Contains(familyCode.Model)
select familyCode.Family).Distinct().ToList();它们生成不同的SQL,自然的第一个选项比第二个选项提供了更复杂的SQL。无论您选择哪种样式,CommonCode的代码都应该遵循相同的模板。
编辑:对于真正的模糊匹配,让我们为一组模型和一组家庭之间的匹配程度开发两个度量。第一个(也是更重要的)措施,我们将称为“覆盖”,这涉及到多少型号包括在家庭。第二个我们称之为"fit",它涉及到在模型集中包含了多少个家庭成员(如果您有两个家族,这两个家族都完全包含所需的模型,我们希望在我们所期望的集合之外有更少的额外模型)。我们将根据比赛的优劣来排序结果,然后取我们能处理的结果的数量。
var fuzzyFamilies = (
from family in familyCodesByFamily
let coverage = desiredModels.Average(dm => family.Any(f => f.Model == dm) ? 1.0 : 0.0)
let fit = family.Average(f => desiredModels.Contains(f.Model) ? 1.0 : 0.0)
orderby coverage descending, fit descending
select family.Key)
.Take(resultCount)
.ToList();https://stackoverflow.com/questions/31841715
复制相似问题