昨天,我问this question关于我开始研究的简单信息检索系统的最佳实践。
今天,我的客户问我是否可以允许他们使用管理界面在以后向主要实体添加字段。也就是说,应用程序允许您搜索一个数据库表(我们称之为实体),这可能与其他对象有各种关联,但重点是实体。
现在,当然,天空是极限,这是可能的。
我最初想到这个问题是创建两个新表:
AdditionalFields (FieldID PK ,FieldName,IsShownInSearchResults和其他元数据) 这是由管理界面创建其行的表。例如,如果客户稍后决定要添加跟踪实体的眼睛颜色的能力,他们会创建一个FieldName为“眼睛颜色”的AdditionalField。
AdditionalFieldData (FieldDataID PK ,EntityID FK ,FieldID FK ,FieldValue)这是与之相关的表格客户添加的任何其他字段的各自值的实体。例如,使用我们的眼睛颜色示例,如果我们在添加字段时有两个实体(实体ID 3和4)并且新的AdditionalField具有FieldID为1,则没有与实体关联的眼睛颜色数据是有效的。 。然后客户可以选择将眼睛颜色“蓝色”添加到实体3,然后我们将这样的行插入到AdditionalFieldData:(自动生成PK ,3,1,“蓝色”)。
由于我想轻松搜索这些内容,我只需要求所有其他字段都包含字符串值。
按照我在上一个问题中发布的方法,当用户执行搜索时,我将使用Linq-To-SQL和类似于以下的查询进行信息检索(当然,过滤的逻辑将更多实践中的复杂性):
var results = from s in db.Stuff
where (s.Name.Contains(textFilter) ||
s.Title.Contains(textFilter))
select s;
我会修改查询,看起来像这样:
var results = from s in db.Stuff
where (...existing filter logic...) ||
s.AdditionalFieldData.Any(afd => afd.FieldName.Contains(textFilter))
select s;
所以我的问题是:这是否合理?我错过了更好的解决方案吗?我应该注意这种方法的含义吗?
(请原谅我的愚蠢标识符,它对我来说很早:)
答案 0 :(得分:1)
我不是LINQ专家,但从数据库设计的角度来看,你的建议似乎对我来说很好。
我见过几次使用的替代方法是在Entities表上定义一大堆'备用'字段,用户可以通过管理界面启用/禁用。您可以通过这种方式获得一些数据库性能(由于连接数较少),但您必须预先选择所需的这些备用字段中的多少,并且在大多数情况下最终会使用大型的空表。 / p>
哦,您可以放心地假设,如果您选择添加 N 备用字段,您的用户将需要 N + 1 ; - )