繁体   English   中英

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

[英]Linq join to perform specific query against 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中正常进行。 所有帮助,不胜感激。

我要使用Linq构建的SQL查询:

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; }
}

问题出在您的要求上:

我想返回主实体的所有实例,在该实例中,它与一个N:N关系中的给定ID关联,而不与另一N:N关系中的相同ID关联。

您无法在Dynamics CRM中使用Linq查询来完成此任务。 Dynamics CRM的Linq查询将转换为QueryExpression查询。 使用QueryExpression不可能选择与其他记录关联的记录。

还要提及的重要一点:LINQ for CRM不支持左外部联接,但QueryExpression查询支持。

您唯一的选择是(希望)多选择一些记录并过滤之后不需要的记录。

提醒一下:当我不得不面对类似的要求时,以下内容对我有用,但这取决于数据,其他自定义设置等,可能会对系统造成性能影响。 必须进行全面测试。

您可以使用插件“欺骗”您的方法。

  1. 为需要跟踪的每个关系向MainEntity添加一个整数字段
  2. 构建一个可计算相关记录的插件,并更新MainEntity中新添加的字段(应在Retrieve / RetrieveMultiple消息上将其注册为Synchronous Post-Operation)。 通过不安全的配置为其提供字段和关系名称,以实现可重用性。

现在,您可以查询MainEntity并知道所需的一切,不需要更多的显式联接(如果需要/也可以将列表作为View使用)。

暂无
暂无

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

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