Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/selenium/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Linq到Sql计数包含联接_C#_Sql Server_Entity Framework_Linq - Fatal编程技术网

C# 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=&

我有一个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=> 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()
应该等于var
membersQ.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();