简体   繁体   English

C#查询基于外键获取行

[英]C# query to fetch row based on foreign key

I have two tables:我有两个表:

Component组件

组件

and Component Profile和组件配置文件

组件配置文件

ComponentId is a foreign key to Component Profile ComponentId是组件配置文件的外键

What I want to do is fetch All Component for a specific Business entity Id and then display all component Profiles for those Component ids from C#我想要做的是获取特定业务实体 ID 的所有组件,然后从 C# 中显示这些组件 ID 的所有组件配置文件

I have been able to retrieve all components for a given business entity id我已经能够检索给定业务实体 ID 的所有组件

var component = context.Components.Where(i => i.BusinessEntityId == businessEntityId ).ToList();

I want to retrieve distinct component ids so that I can get all Component Profiles from it.我想检索不同的组件 ID,以便我可以从中获取所有组件配置文件。 How do i achieve this, Component Id is unique for each Profile.我如何实现这一点,每个配置文件的组件 ID 都是唯一的。 I am hoping that once I get distinct component Ids我希望一旦我获得了不同的组件 ID

foreach (var componentObject in componentObjects)
{
    var componentId = componentObject.Id;
    var componentProfile= context.ComponentProfiles.Where(i => i.ComponentId.Value == componentId);

    if (componentProfile != null)
    {
        result.Add(componentProfile.Map<Libraries.Entities.ComponentProfile>());
    }
}
               

What is an easy way to do this?有什么简单的方法可以做到这一点?

If I understand your question correctly, you can use Include .如果我正确理解您的问题,您可以使用Include

var components = context.Components
     .Include("ComponentsProfiles") // I believe it is plural, but you need to check.
     .Where(i => i.BusinessEntityId == businessEntityId )
     .ToList();

You then loop through components, and get the corresponding component profiles.然后循环遍历组件,并获得相应的组件配置文件。

foreach(var component in components) {
   var componentProfiles = component.ComponentsProfiles;
}

FYI: It is better to have unique identifier column in ComponentProfile table.仅供参考:最好在 ComponentProfile 表中有唯一标识符列。

I renamed your initial variable to be plural, since it returns multiple rows:我将您的初始变量重命名为复数,因为它返回多行:

var components = context.Components.Where(i => i.BusinessEntityId == businessEntityId).ToList();

Now you can group your components by ComponentId so they are distinct:现在,您可以按ComponentId对组件进行分组,使它们不同:

var componentGroups = components.GroupBy(c => c.ComponentId);

Now you can combine the components that have each ComponentId with the ComponentProfile :现在您可以将具有每个ComponentIdComponentProfile组合起来:

var componentProfiles = componentGroups.Select(cg => new { Components = cg.Select(c => c), Profile = context.ComponentProfiles.Single(cp => cp.ComponentId == cg.Key) });

So componentProfiles is an anonymous object that combines the list of Components rows with what I enforced is the single ComponentProfiles row that they use.所以componentProfiles是一个匿名对象,它将Components行列表与我强制执行的是它们使用的单个ComponentProfiles行。

This solution combines all the code into a single Linq query.此解决方案将所有代码组合到一个 Linq 查询中。

var context = GetCoreDbEntityContext(businessEntityId);
var result = context.Components
    .Where(i => i.BusinessEntityId == businessEntityId)    // find relevant components
    .Select(c => new { c.ComponentId, c.BusinessEntityId })    // isolate the fields needed
    .Distinct()    // find distinct combinations of fields
    .Join(    // inner join distinct combinations with ComponentProfiles
        context.ComponentProfiles,    // table or list to inner join with
        c => c.ComponentId,    // key selector from Components used in join
        p => p.ComponentId,    // key selector from ComponentProfiles used in join
        (c, p) => new {    // select individual fields or table(s) as needed
            c.BusinessEntityId,    // individual component business entity ID
            c,    // all Component fields
            p    // all ComponentProfile fields
        })
    .Select(r => r.p)    // (optional) reduce columns to only ComponentProfiles
    .ToList();

return result;    // contains list of ComponentProfiles

Alternatively, if you only need the componentProfiles, you could do this.或者,如果您只需要 componentProfiles,您可以这样做。

var context = GetCoreDbEntityContext(businessEntityId);
var result = context.ComponentProfiles
    .Where(p => context.Components
        .Where(i => i.BusinessEntityId == businessEntityId)    // find relevant components
        .Any(c => c.ComponentId == p.ComponentId)    // include rows with matching ComponentId
    ).ToList();

return result;    // contains list of ComponentProfiles

This seemed to work out from all the pieces answered:这似乎从所有回答的部分中得到解决:

 try
        {
            var context = GetCoreDbEntityContext(businessEntityId);
            var components = context.Components.Where(i => i.BusinessEntityId == businessEntityId).ToList();
            var componentIdsDistinct = components.Select(c => c.Id).Distinct();

            foreach (var componentId in componentIdsDistinct)
            {
                var componentProfile = context.ComponentProfiles.SingleOrDefault(i => i.ComponentId == componentId);
                if (componentProfile != null)
                {
                    result.Add(componentProfile.Map<Libraries.Entities.ComponentProfile>());
                }
            }
            return result;
        }

There is a one-to-many relation between Profiles and Components : ProfilesComponents之间存在一对多关系:

  • Every Component has exactly one Profile (using a foreign key with a rather confusing name. I'll use ProfileId );每个Component都只有一个Profile (使用名称相当混乱的外键。我将使用ProfileId );
  • Every Profile may be used by zero or more Components .每个Profile可以被零个或多个Components

Because one Profile may be used by several Components , there may be several 'Components' with the same foreign key value 'ProfileId`因为一个Profile可能被多个Components ,所以可能有多个具有相同外键值 'ProfileId` 的 'Components'

I want to fetch All Component for a specific Business entity Id and then display all component Profiles for those Component ids我想获取特定业务实体 ID 的所有组件,然后显示这些组件 ID 的所有组件配置文件

So given a businessEntityId , you need to find all Components with this businessEntityId .因此,给定一个businessEntityId ,您需要找到具有此businessEntityId所有Components Once you've got these components, you can find the Profiles that belong to these components.获得这些组件后,您可以找到属于这些组件的Profiles As said, several Components may belong to the same Profile , so you'll have to use Distinct to remove duplicates.如前所述,多个Components可能属于同一个Profile ,因此您必须使用Distinct删除重复项。

var result = MyComponents
    // keep only the components with businessEntityId
    .Where(component => component.BusinessEntityId == businessEntitId)
    .Join(MyProfiles,                      // Join with Profiles
        component => component.ProfileId,  // from every component take the foreign key
        profile => profile.Id,             // from every profile take the primary key
        (component, profile) =>            // when they match
            profile)                       // keep the matching profile
    .Distinct()                            // and remove duplicates

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM