我正在写一个基于标签的ASP.net系统。使用以下数据库方案:Topic <many-many> TagTopicMap <many-many> Tag
基本上,这是我从以下内容中发现的3NF方法(毒素):http://www.pui.ch/phred/archives/2005/04/tags-database-schemas.html
这是我的代码片段:
DataLoadOptions options = new DataLoadOptions();
options.LoadWith<Topic>(t => t.TagTopicMaps);
options.LoadWith<TagTopicMap>(tt => tt.Tag);
var db = new lcDbDataContext();
db.LoadOptions = options;
db.Log = w;
var x = from topic in db.Topics
orderby topic.dateAdded descending
select topic;
ViewData["TopicList"] = x.Take(10);
当我执行此操作时,结果很好,但是它带有11个单个SQL查询,一个用于获取前10个主题的列表:
SELECT TOP (10) [t0].[Id], [t0].[title], [t0].[dateAdded]
FROM [dbo].[Topics] AS [t0] ORDER BY [t0].[dateAdded] DESC
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.30729.1
其他十个用于分别获取标签的详细信息。
我试图打开和关闭两个loadwith语句,发现发生了以下事情:
loadwith<topic> : no difference for on or off.
loadwith<tagtopicmap>: 11 Queries when on, much more when off.
简而言之,只有第二个loadwith选项可以正常工作。第一个没有任何作用!
我还尝试使结果集为ToList()。但是还会出现更多问题:对于标签详细信息部分,它仅检索那些UNIQUE项,所有那些重复的标签(当然,相同的标签可能会出现在多个主题中!)被查询删除。
最后一件事,下面是我在aspx中用于检索数据的代码,如果将结果设置为list(),则将(IQueryable)更改为(IList):
<% foreach (var t in (IQueryable)ViewData["TopicList"])
{
var topic = (Topic)t;
%>
<li>
<%=topic.title %> ||
<% foreach (var tt in (topic.TagTopicMaps))
{ %>
<%=tt.Tag.Name%>,
<%} %>
</li>
<%
}
%>
最佳答案
简短的答案是:LinqToSql有几个类似的怪癖,有时您必须使用变通方法...
Linq2Sql LoadWith选项仅导致数据库表之间的内部联接,因此您可以通过将Linq语句改写为类似内容(请原谅任何错别字,我习惯用VB语法编写Linq ...)来强制执行类似的行为:
var x = from topic in db.Topics
join topicMap in topic.TagTopicMaps
orderby topic.dateAdded descending
group topicMap by topicMap.topic into tags = Group;
这种语法可能是非常错误的,但是基本思想是您迫使Linq2Sql评估Topics和TagTopicMaps之间的联接,然后使用分组(或“group join”,“let”等)将对象层次结构保留在结果集。
关于c# - LINQ options.loadwith问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/880734/