LINQ 与 ManyToMany:基于多项选择的过滤

发布于 2024-12-28 07:49:39 字数 709 浏览 1 评论 0原文

我是 C# 新手,必须在我的硕士论文中使用它。目前,我面临着一个对我来说有点复杂的问题。

我已经建立了一个具有多对多关系的数据库,如下所示:

Table Relay:  
- id (PK)  
- Name  
- Input  

Table ProtectionFunction:  
- id (PK)  
- ANSI  
- IEC  
- Description  

Table RelayConfig (junction table)  
- RelayID (PK)  
- ProtFuncID (PK)  
- TimeToSaturate  
- Remanence  

问题是,Relay 可以具有多个保护功能,并且对于每个保护功能,它都有特定的 TimeToSaturate 值代码>和<代码>剩磁。现在我想实现一个过滤器。用户可以通过DataGridView中的复选框选择保护功能,并且ListBox应该显示支持所有这些保护功能的所有Relay

我已经为我的项目创建了 LINQ-to-SQL 类。但现在我陷入困境,因为我不知道如何实现过滤。到目前为止我发现的所有 LINQ 命令都会为我提供一种保护功能的所有Relay

我真的希望你们中的一位能给我一个提示。

I am a newbe to C# and have to use it for my master thesis. At the moment, I am facing a problem that is a bit to complex for me.

I have set up a database with a many-to-many relationship like this:

Table Relay:  
- id (PK)  
- Name  
- Input  

Table ProtectionFunction:  
- id (PK)  
- ANSI  
- IEC  
- Description  

Table RelayConfig (junction table)  
- RelayID (PK)  
- ProtFuncID (PK)  
- TimeToSaturate  
- Remanence  

The thing is, a Relay can have multiple protection functions, and for each it has specific values for TimeToSaturate and Remanence. Now I want to realize a filter. The user can select protection function via checkboxes in a DataGridView and a ListBox should show all Relays that support ALL of these protection functions.

I have already created the LINQ-to-SQL classes for my project. But now I am stuck because I don't know how to realize the filtering. All LINQ commands I have found so far would give me all Relays for one protection function.

I really hope one of you can give me a hint.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

枯寂 2025-01-04 07:49:39
var ids = new int[]{ ... }; 
// if ids is null or ids.Length == 0 please return null or an empty list, 
//do not go further otherwise you'll get Relays without any function filter

var query = Relays.AsQueryable(); 
foreach (var id in ids)    
{
     var tempId = id;
     query = query.Where(r=>r.RelayConfigs.Any(rc=>rc.ProtFuncID == tempId)); 
}
var items  = query.ToList();

更新
刚刚在 PredicateBuilder 页面上看到了这个:

循环中需要临时变量以避免外部
变量陷阱,每次迭代都会捕获相同的变量
foreach 循环。

var ids = new int[]{ ... }; 
// if ids is null or ids.Length == 0 please return null or an empty list, 
//do not go further otherwise you'll get Relays without any function filter

var query = Relays.AsQueryable(); 
foreach (var id in ids)    
{
     var tempId = id;
     query = query.Where(r=>r.RelayConfigs.Any(rc=>rc.ProtFuncID == tempId)); 
}
var items  = query.ToList();

Update
Just saw this on PredicateBuilder page:

The temporary variable in the loop is required to avoid the outer
variable trap, where the same variable is captured for each iteration
of the foreach loop.

︶ ̄淡然 2025-01-04 07:49:39

如果从 RelayConfigs 开始会更容易。像这样的事情应该有效:

 var protFuncIds = new[]{1,2,3};
 var query = from rc in db.RelayConfigs
             where protFuncIds.Contains(rc.ProtFuncID)
             select rc.Relay;
 var relays = query.Distinct().ToList();

更新:
根据您的评论,以下内容应该有效,但是请监视生成的 SQL...

IQueryable<Relay> query = db.Relays

foreach (var id in ids)
   query = relays.Where(r => r.RelayConfigs.Select(x => x.ProtFuncId).Contains(id));

var relays = query.ToList();

It's easier if you start from the RelayConfigs. Something like this should work:

 var protFuncIds = new[]{1,2,3};
 var query = from rc in db.RelayConfigs
             where protFuncIds.Contains(rc.ProtFuncID)
             select rc.Relay;
 var relays = query.Distinct().ToList();

UPDATE:
based on your comment, the following should work, however do monitor the SQL generated...

IQueryable<Relay> query = db.Relays

foreach (var id in ids)
   query = relays.Where(r => r.RelayConfigs.Select(x => x.ProtFuncId).Contains(id));

var relays = query.ToList();
单身狗的梦 2025-01-04 07:49:39
// Build a list of protection function ids from your checkbox list
var protFuncIDs = [1,2,3,4];

using(var dc = new MyDataContext())
{
    var result = dc.Relays.Where(r=>protFuncIDs.Join(r.RelayConfigs, pf=>pf, rc=>rc.ProtFuncID, (pf,rc)=>pf).Count() == protFuncIDs.Length).ToArray();
}

它不是特别有效,但这应该对你有用。

// Build a list of protection function ids from your checkbox list
var protFuncIDs = [1,2,3,4];

using(var dc = new MyDataContext())
{
    var result = dc.Relays.Where(r=>protFuncIDs.Join(r.RelayConfigs, pf=>pf, rc=>rc.ProtFuncID, (pf,rc)=>pf).Count() == protFuncIDs.Length).ToArray();
}

It's not especially efficient, but that should do the trick for you.

狼亦尘 2025-01-04 07:49:39

我已经在 Lightswitch 中完成了此操作,这是我的预处理查询:

partial void UnusedContactTypesByContact_PreprocessQuery(int? ContactID, ref IQueryable<ContactType> query)
    {
        query = from contactType in query
                where !contactType.ContactToContactTypes.Any(c => c.Contact.Id == ContactID)
                select contactType;
    }

希望有所帮助。

I have done this in Lightswitch, and here was my preprocess query:

partial void UnusedContactTypesByContact_PreprocessQuery(int? ContactID, ref IQueryable<ContactType> query)
    {
        query = from contactType in query
                where !contactType.ContactToContactTypes.Any(c => c.Contact.Id == ContactID)
                select contactType;
    }

Hope that helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文