2015-07-21 52 views
0

我正在尋找一些有關特定Linq連接查詢的幫助。我的Linq知識是相當基礎的,我一直在努力拼寫正確的連接代碼。Linq加入以針對Dynamics CRM 2015執行特定查詢

我實際上正在嘗試構建一個Linq查詢,該查詢將與使用由CrmSvcUtil.exe實用程序生成的ServiceContext的Dynamics CRM Online 2015 SDK一起使用。

顯然,CRM Linq Provider(ref1,ref2ref3等)存在侷限性。當使用我熟悉的那種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提供商沒有直接的經驗,它仍然可以幫助我瞭解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提供程序的限制)。該列表必須是而不是,與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; } 
} 
+0

您可以添加類建模嗎? – Andre

+0

正如我所說,我的真實生活挑戰與自動生成的巨大的CRM類模型有關。你在問這些問題,還是僅僅是一些類可以用我簡單的SQL例子呢? – getsetcode

+0

只是示例中的類 – Andre

回答

1

問題就出在你的要求:

我想回到的地方是與給定ID相關聯 主要實體的所有實例在一個N:N的關係,並沒有關聯 在另一個N:N關係中具有相同的ID。

您無法使用Dynamics CRM中的Linq查詢完成此操作。 Dynamics CRM的Linq查詢轉換爲QueryExpression查詢。使用QueryExpression不可能選擇與其他記錄關聯的記錄而不是

同樣重要的是:左外部連接不受LINQ for CRM支持,但受QueryExpression查詢支持。

您唯一的選擇是選擇(希望)更多的記錄和過濾後不需要的記錄。

+0

謝謝,至少這意味着我必須完全改變我的方法,而不是讓我的頭撞在這堵磚牆上。感謝您的建議。 – getsetcode

+0

我很同情你。忘了提及LINQ for CRM不支持左外連接。這是將他們推到一邊並使用QueryExpression查詢的強烈動機。我將這添加到我的答案中。 –

+0

再次感謝。 QueryExpression的問題是我需要硬編碼所有的實體和屬性名稱。使用CrmSvcUtil.exe實用程序生成的強類型實體更加優雅。無論如何,我正在研究一種不需要左連接的新方法。祝我好運:) – getsetcode

1

一句警告:下面的工作對我來說,當我不得不面對類似的要求,但它可能是一個性能命中該系統根據數據,其他自定義,等徹底的測試是必須的

你可以用插件「欺騙」你的方式。

  1. 整數字段添加到MainEntity爲每個需要跟蹤的
  2. 建設,其對相關記錄並更新MainEntity新增領域(這應該被註冊爲同步後的一個插件關係在Retrieve/RetrieveMultiple消息上操作)。通過不安全的配置將其字段和關係名稱提供給可重用目的。

現在,您可以查詢MainEntity,知道你所需要的一切,沒有更多的明確連接需要(你也可以擁有列表作爲視圖如果您需要/想它)。

+1

感謝您的建議。然而基於@ henk-van-boeijen的建議,我決定研究一種新的數據模型,而不是希望這意味着我不需要'欺騙'! – getsetcode

+0

如果數據不是一成不變的,那麼將其重組爲最佳行動方案 – Alex