Linq加入以针对Dynamics CRM 2015执行特定查询

时间:2015-07-21 17:44:42

标签: c# asp.net linq dynamics-crm-2015

我正在寻找特定Linq联接查询的帮助。我的Linq知识非常基础,我一整天都在努力编写正确的连接代码。

我实际上正在尝试使用CrmSvcUtil.exe实用程序生成的ServiceContext构建一个可与Dynamics CRM Online 2015 SDK一起使用的Linq查询。

显然,CRM Linq提供商存在限制(ref1ref2ref3等。当使用Linq查询时,我熟悉我经常会得到以下错误。似乎答案是使用更自然的Linq加入。

Invalid 'where' condition. An entity member is invoking an invalid property or method.

我认为不应该向您展示我100多次失败的尝试,而是使用SQL示例来演示我想要实现的目标。下面的示例脚本。基本上我有一个实体,我想要返回一个记录列表。这与另一个实体有两个N:N关系。我想返回主实体的所有实例,它与一个N:N关系中的给定ID相关联,而不与其他N:N关系中的相同ID相关联。

我最挣扎的部分是执行包含内连接和左外连接的Linq查询。即使您没有直接使用CRM Linq Provider的经验,它仍然可以帮助我看看如何在Linq中正常完成。所有人都非常感激。

SQL查询我想用Linq构建:

DECLARE @id INT = 1

-- Should only return entities with IDs 1 and 2
SELECT a.* FROM [dbo].[MainEntity] a
INNER JOIN [dbo].[AltOne] b ON a.EntityID = b.EntityID AND b.AltOneID = @id
LEFT JOIN [dbo].[AltTwo] c ON a.EntityID = c.EntityID AND c.AltOneID = @id
WHERE c.AltOneID IS NULL

数据库设置脚本:

CREATE TABLE [dbo].[MainEntity](
    [EntityID] [int] NOT NULL,
    [EntityName] [varchar](50) NOT NULL,
    CONSTRAINT [PK_MainEntity] PRIMARY KEY CLUSTERED 
    ( 
        [EntityID] ASC 
    )
)
GO

CREATE TABLE [dbo].[AltOne](
    [EntityID] [int] NOT NULL,
    [AltOneID] [int] NOT NULL,
    CONSTRAINT [PK_AltOne] PRIMARY KEY CLUSTERED 
    (
        [EntityID] ASC,
        [AltOneID] ASC
    )
)
GO

ALTER TABLE [dbo].[AltOne]  WITH CHECK ADD  CONSTRAINT [FK_AltOne_MainEntity] FOREIGN KEY([EntityID])
REFERENCES [dbo].[MainEntity] ([EntityID])
GO

ALTER TABLE [dbo].[AltOne] CHECK CONSTRAINT [FK_AltOne_MainEntity]
GO

CREATE TABLE [dbo].[AltTwo](
    [EntityID] [int] NOT NULL,
    [AltOneID] [int] NOT NULL,
    CONSTRAINT [PK_AltTwo] PRIMARY KEY CLUSTERED 
    (
        [EntityID] ASC,
        [AltOneID] ASC
    )
)
GO

ALTER TABLE [dbo].[AltTwo]  WITH CHECK ADD  CONSTRAINT [FK_AltTwo_MainEntity] FOREIGN KEY([EntityID])
REFERENCES [dbo].[MainEntity] ([EntityID])
GO

ALTER TABLE [dbo].[AltTwo] CHECK CONSTRAINT [FK_AltTwo_MainEntity]
GO

INSERT INTO [dbo].[MainEntity] ([EntityID], [EntityName]) VALUES (1, 'Test 1')
INSERT INTO [dbo].[MainEntity] ([EntityID], [EntityName]) VALUES (2, 'Test 2')
INSERT INTO [dbo].[MainEntity] ([EntityID], [EntityName]) VALUES (3, 'Test 3')
GO

INSERT INTO [dbo].[AltOne] ([EntityID], [AltOneID]) VALUES (1, 1)
INSERT INTO [dbo].[AltOne] ([EntityID], [AltOneID]) VALUES (1, 2)
INSERT INTO [dbo].[AltOne] ([EntityID], [AltOneID]) VALUES (2, 1)
INSERT INTO [dbo].[AltOne] ([EntityID], [AltOneID]) VALUES (2, 2)
INSERT INTO [dbo].[AltOne] ([EntityID], [AltOneID]) VALUES (3, 1)
GO

INSERT INTO [dbo].[AltTwo] ([EntityID], [AltOneID]) VALUES (3, 1)
INSERT INTO [dbo].[AltTwo] ([EntityID], [AltOneID]) VALUES (1, 2)
INSERT INTO [dbo].[AltTwo] ([EntityID], [AltOneID]) VALUES (2, 2)
GO

修改1:

按要求添加示例类。重申一下,我需要返回MainEntity个对象的集合,而不直接使用ICollection属性并使用连接(这似乎是CRM Linq Provider的限制) 。该列表必须是与特定RelatedEntity通过CollectionOne相关的对象,但 与同一RelatedEntity相关CollectionTwo。我希望这很清楚。

public class MainEntity
{
    public int EntityID { get; set; }
    public string EntityName { get; set; }

    public ICollection<RelationshipOne> CollectionOne { get; set; }
    public ICollection<RelationshipTwo> CollectionTwo { get; set; }
}

public class RelationshipOne
{
    public int EntityID { get; set; }
    public int AltOneID { get; set; }

    public ICollection<MainEntity> MainEntities { get; set; }
    public ICollection<RelatedEntity> RelatedEntities { get; set; }
}

public class RelationshipTwo
{
    public int EntityID { get; set; }
    public int AltOneID { get; set; }

    public ICollection<MainEntity> MainEntities { get; set; }
    public ICollection<RelatedEntity> RelatedEntities { get; set; }
}

public class RelatedEntity
{
    public int RelatedEntityID { get; set; }
    public string RelatedEntityName { get; set; }

    public ICollection<RelationshipOne> RelationshipOnes { get; set; }
    public ICollection<RelationshipTwo> RelationshipTwos { get; set; }
}

public class DummyContext
{
    public System.Data.Entity.DbSet<MainEntity> MainEntitySet { get; set; }
    public System.Data.Entity.DbSet<RelationshipOne> RelationshipOneSet { get; set; }
    public System.Data.Entity.DbSet<RelationshipTwo> RelationshipTwoSet { get; set; }
    public System.Data.Entity.DbSet<RelatedEntity> RelatedEntitySet { get; set; }
}

2 个答案:

答案 0 :(得分:1)

问题在于您的要求:

  

我想返回主实体的所有实例   与一个N:N关系中的给定ID相关联,并且不相关联   在其他N:N关系中使用相同的ID。

使用Dynamics CRM中的Linq查询无法实现此目的。针对Dynamics CRM的Linq查询将转换为QueryExpression个查询。使用QueryExpression,无法选择与其他记录关联的记录。

同样重要的是:LINQ for CRM不支持左外连接,但QueryExpression查询支持左外连接。

您唯一的选择是选择(希望)更多的记录,然后过滤掉之后不需要的记录。

答案 1 :(得分:1)

一句警告:当我不得不面对类似的要求时,以下内容对我有用,但根据数据,其他自定义等,它可能会对系统造成性能损失。彻底的测试是必须即可。

你可以&#34;作弊&#34;通过这个插件你的方式。

  1. 为MainEntity添加一个整数字段,用于跟踪
  2. 所需的每个关系
  3. 构建一个插件,用于计算相关记录并更新MainEntity中新添加的字段(这应该在Retrieve / RetrieveMultiple消息上注册为同步后操作)。通过不安全的配置为字段和关系名称提供可重用性。
  4. 您现在可以查询MainEntity并了解您需要的所有内容,不需要更多显式连接(如果您需要/想要它,您也可以将列表作为视图)。