C# Linq到Sql计数包含联接
我有一个Linq到sql,如下所示:C# Linq到Sql计数包含联接,c#,sql-server,entity-framework,linq,C#,Sql Server,Entity Framework,Linq,我有一个Linq到sql,如下所示: var members=db.Members.Include(x=> x.Contact).Count(); 现在由于一些坏数据,我的成员中的所有联系人都没有相应的联系人记录。因此,在计数过程中,如何在联系人表内部联接之后包含计数 问题是,当我获得成员列表时,成员列表有100条记录,而Count有150条记录(50条记录是坏数据) var membersQ=db.Members.Include(x=> x.Contact).Select(i=&
var members=db.Members.Include(x=> x.Contact).Count();
现在由于一些坏数据,我的成员中的所有联系人都没有相应的联系人记录。因此,在计数过程中,如何在联系人表内部联接之后包含计数
问题是,当我获得成员列表时,成员列表有100条记录,而Count有150条记录(50条记录是坏数据)
var membersQ=db.Members.Include(x=> x.Contact).Select(i=> new MemberViewModel(){
Name = i.Contact.Name,
ContactId= i.Contact.Id,
CreatedDate= i.CreatedDate
}).AsQueryable();
var members=memberQ.ToList();// =100,paging is done...
// the memebers list uses paging but the count doesn't
var total=membersQ.Count(); // =150
我在count期间检查了结果查询,显然它不与Contact table进行JOIN
,而count()
更新
数据库结构
Member Table
Id ContactId, CompanyId, CreatedDate ...
Contact Table
Id Name ...
成员表中ContactId的外键不是在数据库级别设置的,而是仅在模型上设置的
[ForeignKey("ContactId")]
Public Contact Contact { get; set; }
坏数据是这样的
我以前有1,2,3,4,5,6,7,8,9,10作为联系人记录,所有这些联系人也都在成员表中
现在我删除了联系人表中的记录,比如说6-10。但碰巧没有从成员表中删除
所以这导致了计数的问题。当然,从成员中删除坏数据可以解决问题,但问题是如何在使用Count()时使用join
注意:我使用数据库初始值设定项null
更新2
我使用了LinqPad并尝试了默认的linqtosql
和EntityFramework
(DbContext)连接,但我发现这两种连接都很混乱
查询:
(from a in Members
join b in Contacts on a.ContactId equals b.ContactId
select a).Count()
使用默认Linq到SQL
SELECT COUNT(*) AS [value]
FROM [Member] AS [t0]
INNER JOIN [Contact] AS [t1] ON [t0].[ContactID] = [t1].[ContactID]
使用Entityframework DbContext
SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
COUNT(1) AS [A1]
FROM [dbo].[Member] AS [Extent1]
) AS [GroupBy1]
在我的代码中,我使用DbContext方法。所以我不知道在这里该做什么
.
顺便说一句:很抱歉有一个带有
linq to sql
的标记,它实际上是entityframework
不确定这是否正确,但是,记录是否包含错误数据,是否重复?如果是,那么为什么不使用distinct()只获取这100条好记录呢?如果您只需要列表中的计数,那么为什么不使用:
var members = memberQ.ToList();
int total = members.Count;
答案是,您与会员和联系人之间没有任何联系。成员表有150行,联系人表有100行。因此,当您尝试获取数据时,实际上是逐行配对数据,直到某个表完成。当你数的时候,你数的是第一张桌子 解决方案您需要向来自成员的联系人添加一个FK或任何类型的标识符,您可以将数据“绑定”到来自联系人的成员 更多解释&更多评论 在表
Members
中,您有一个对联系人的引用。您使用Include(x=>x.Contact)
语句填充它
所以当你试着做这个的时候
new MemberViewModel(){
Name = i.Contact.Name,
ContactId= i.Contact.Id,
CreatedDate= i.CreatedDate
}
您正在请求联系人的内容(您可能知道)
现在来做一些解释。当您在MembersQ
中查询数据库时,您并没有获取/实现数据。(您只是准备一个查询)
要实现查询,必须调用ToArray()
,ToList()
等,并且在对数据执行foreach
时,每次实现一行(光标)
现在,对于您的结果,当您调用ToList()时,您正在实现类型列表的列表(现在只使用能够填充的元素(这是您的100))
当您执行memberQ.Count()
时,您会要求数据库对查询进行计数,因为数据库对MemberViewModel
一无所知,它将返回与可能的匹配的成员计数,其中(x=>{filter})
(这是您的150)
一个简单的修复方法是编写ToList()
而不是AsQueryable()
。我对LINQ to SQL有些生疏,您可能必须执行AsQueryable().ToList()
一个可能的解决办法是预先过滤
var membersQ=db.Members.Include(x=> x.Contact).Where(a=> a.Contact != null).Select(i=> new MemberViewModel(){
Name = i.Contact.Name,
ContactId= i.Contact.Id,
CreatedDate= i.CreatedDate
}).AsQueryable();
现在membersQ.Count()
应该等于varmembersQ.ToList().Count()
要执行分页,请使用memberQ.Skip(x).Take(y)
这将在SQL上执行,而不是在Web服务器上执行。除非您ToList()
,否则一切都在服务器上,因为它突然成为服务器内存中的一组数据
如果不起作用,那么您没有外键,您可以将过滤器更改为在ContactID中过滤,而不是在Contact中过滤。添加FK(外键)的步骤
添加外键:如果您有权修改SQL,则将成员中的ContactID设置为空,并从成员ContactID和联系人ID中添加外键
然后从dbml中删除这两个表,并从db资源管理器中将它们再次拖入。现在,您应该能够简单地使用不包含的代码,因为它将是“延迟加载”(意味着不包含)而不是“急切加载”(意味着您必须说要加载什么)这是怎么回事:
var x = from m in Members
join c in Contacts on m.ContactId equals c.ID
select new
{
Name = c.Name,
ContactId= c.ID,
CreatedDate= c.CreatedDate
};
Console.Write(x.Count());
编辑
当我将LinqPad用于此查询并查看生成的SQL时,我得到:
SELECT COUNT(*) AS [value]
FROM [Members] AS [t0]
INNER JOIN [Contact] AS [t1] ON [t0].[ContactId] = ([t1].[ID])
编辑2
您也可以尝试以下方法:
var x = from c in Contacts
from m in Members where m.ContactId == c.ID
select new
{
Name = c.Name,
ContactId= c.ID,
CreatedDate= c.CreatedDate
};
Console.Write(x.Count());
这就是你想要的吗?试试这个
var members=db.Members.Include(x=> x.Contact)
.Where(x => x.Contact != null)
.Count();
为了举例,我直接使用了ToList,但我需要在记录中进行分页。计数不需要分页。只是为了好玩。尝试memberQ.Contacts.Count()(应该是100),因此我必须使用不同的查询来选择联系人
,而不是用于ToList
?是的,ToList
确实解决了问题,但又产生了另一个问题。数据太多ToList
将列出数据库中的所有记录,使用分页时不需要这些记录。是的,我没有举一个分页的例子,但是我在帖子中引用了分页。计数是数据库中没有分页的记录总数。在底部添加了一个示例,看看这是否有用我使用了a.Contact!=空
,它仍然不起作用。结果查询在Count()
Ohh上没有联接或检查现有的Contact
。嗯,这似乎意味着您实际上没有外键。另一件事,将设置为Where
var members=db.Members.Include(x=> x.Contact)
.Where(x => x.Contact != null)
.Count();