Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/256.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.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连接(lambda)上添加where子句?_C#_Asp.net_Linq_Lambda - Fatal编程技术网

C# 如何在linq连接(lambda)上添加where子句?

C# 如何在linq连接(lambda)上添加where子句?,c#,asp.net,linq,lambda,C#,Asp.net,Linq,Lambda,我有两个数据库表联系人Id,姓名。。。和ContactOperationalPlaces ContactId,市政ID,其中一个联系人可以连接到多个ContactOperationalPlaces 我要做的是构建一个查询ASP.NET,C和IQueryable,它只选择ContactOperationalPlaces表中存在的所有联系人,并使用给定的市政ID sql查询如下所示: select * from Contacts c right join ContactOperationPlace

我有两个数据库表联系人Id,姓名。。。和ContactOperationalPlaces ContactId,市政ID,其中一个联系人可以连接到多个ContactOperationalPlaces

我要做的是构建一个查询ASP.NET,C和IQueryable,它只选择ContactOperationalPlaces表中存在的所有联系人,并使用给定的市政ID

sql查询如下所示:

select * from Contacts c 
right join ContactOperationPlaces cop on c.Id = cop.ContactId 
where cop.MunicipalityId = 301;
//_ctx is the context
var tmp = (from c in _ctx.Contacts
             join cop in _ctx.ContactOperationPlaces on c.Id equals cop.ContactId
             where cop.MunicipalityId == 301
             select c);
IQueryable<Contacts> query = (from c in _ctx.Contacts select c);

...

query = query.Where(x=> x.Name.ToLower().Contains(nameStr.ToLower());

...

IQueryable<ContactOperationPlaces> query_2 =
     (from c in _ctx.ContactOperationPlaces
       where query.Where(x=> x.Name == c.Contact.Name).Count() > 0
       select c);

 //Now query_2 contains all contactoperationsplaces which have a contact that was found in var query
对于linq,它看起来像这样:

select * from Contacts c 
right join ContactOperationPlaces cop on c.Id = cop.ContactId 
where cop.MunicipalityId = 301;
//_ctx is the context
var tmp = (from c in _ctx.Contacts
             join cop in _ctx.ContactOperationPlaces on c.Id equals cop.ContactId
             where cop.MunicipalityId == 301
             select c);
IQueryable<Contacts> query = (from c in _ctx.Contacts select c);

...

query = query.Where(x=> x.Name.ToLower().Contains(nameStr.ToLower());

...

IQueryable<ContactOperationPlaces> query_2 =
     (from c in _ctx.ContactOperationPlaces
       where query.Where(x=> x.Name == c.Contact.Name).Count() > 0
       select c);

 //Now query_2 contains all contactoperationsplaces which have a contact that was found in var query
所以,我知道如何做到这一点,如果一次选择所有这些,不幸的是它不是。我正在根据用户输入构建一个查询,所以我不能一次知道所有的选择

这就是我的代码的样子:

IQueryable<Contacts> query = (from c in _ctx.Contacts select c);
//Some other logic....
/*Gets a partial name (string nameStr), and filters the contacts 
 so that only those with a match on names are selected*/
query = query.Where(c => c.Name.Contains(nameStr);
//Some more logic
//Gets the municipalityId and wants to filter on it! :( how to?
query = query.where(c => c.ContactOperationalPlaces ...........?);
此表达式返回的对象是System.Linq.Iqueryable,无法将其强制转换为联系人


这就是问题所在。答案可能很简单,但我就是找不到它…

你能把它转换成var并尝试使用intellisense吗

 var myCast = query.Join(_ctx.ContactOperationPlaces, c => c.Id, cop => cop.ContactId,
  (c, cop) => new {c, cop}).Where(o => o.cop.municipalityId == 301);

只是一个想法

在where子句之前创建一个包含两个对象的匿名类型,并在ContactOperationPlaces值上对其进行过滤。你只需要在那之后选择联系人

query.Join(_ctx.ContactOperationPlaces, c => c.Id, cop => cop.ContactId,
           (c, cop) => new {c, cop}).Where(o => o.cop.municipalityId == 301)
                                    .Select(o => o.c)
                                    .Distinct();

您不需要在结果选择器函数中返回新对象。委托提供了两个变量,因此您可以选择其中一个变量,或者需要新对象的其他变量。试试这个:

query.Join(_ctx.ContactOperationPlaces, c => c.Id, cop => cop.ContactId,
  (c, cop) => c).Where(o => o.cop.municipalityId == 301);

我认为,如果您以两个不同的查询开始,然后将它们组合在一起,那么会容易得多。我假设关系是Contact 1多个Contact操作地点?最后,您将为每个联系人显示1项OperationPlaces,而不是每个联系人显示1项

这样做:

select * from Contacts c 
right join ContactOperationPlaces cop on c.Id = cop.ContactId 
where cop.MunicipalityId = 301;
//_ctx is the context
var tmp = (from c in _ctx.Contacts
             join cop in _ctx.ContactOperationPlaces on c.Id equals cop.ContactId
             where cop.MunicipalityId == 301
             select c);
IQueryable<Contacts> query = (from c in _ctx.Contacts select c);

...

query = query.Where(x=> x.Name.ToLower().Contains(nameStr.ToLower());

...

IQueryable<ContactOperationPlaces> query_2 =
     (from c in _ctx.ContactOperationPlaces
       where query.Where(x=> x.Name == c.Contact.Name).Count() > 0
       select c);

 //Now query_2 contains all contactoperationsplaces which have a contact that was found in var query
相反,有一种更简单的方法可以做到这一点,那就是完全跳过第一部分

IQueryable<ContactOperationPlaces> query_2 =
     (from c in _ctx.ContactOperationPlaces
       where c.Contact.Name.ToLower().Contains(strName.ToLower())
       select c);
如果您使用的是实体框架,只要定义了表之间的关联,就不必进行任何连接

现在我看了一下,我的第二个解决方案更加高效和简单。但如果您需要在这些命令之间进行其他处理,解决方案一也可以:


如果您需要更多解释,请随时询问:

,并可能为Contacts添加Distinct谢谢!我知道一旦我找到它,解决方案就会非常简单。我以前试过这个,因为我不喜欢这样做:c,cop=>new{c,cop},我将没有机会在where子句中选择cop…我想在contactoperationalplaces中保留与特定市政ID有连接的联系人,所以我希望每个联系人都有一个项目。我知道后一种解决方案是最好的,但正如我在问题中所解释的,我不能同时选择所有表。这些不同的表是否通过一对多关联连接?如果是这样,这是你最好的解决方案。如果您有contact所依赖的其他联接,则应通过执行类似于上述的操作来替换这些联接。由于EF为您执行所有连接,您只需说出您想要的内容,因此我认为默认情况下,针对EF手动连接表是低效的,可能除了一些非常非常不寻常的情况。不怪你,但我建议你不要手动连接,因为你需要做更多的工作,更少的反馈/调试。。。