2014-04-08 3 views
1

내가 .NET Framework의 특정 SDK에 있어요, 나 데이터 저장소에 대한 식을 작성하고 나에게 결과를 반환 할 수 있습니다 (이 질문에 그러나 중요하지, CRM SDK 단지 배경). 여기서 은 쿼리 이 실제로 실행될 때 쿼리가 실행될 때 묻는 에 의존한다는 것입니다.이니셜 라이저에 객체 인스턴스를 설정하고 즉시 속성에 액세스하는 방법은 무엇입니까?

그래서 6000 개 항목이 식을 실행하는 경우는 모든 120 열과 모든 레코드를 반환하는 데 5 분 정도 걸릴 수 있습니다. 그러나 5-6 개의 필드/열에 대해서만 요청하면 6000 개의 모든 항목을 반환하는 데 5-10 초 정도 걸릴 수 있습니다. 여기에서 중요한 키는 객체 이니셜 라이저에서 모든 필드에 대해 묻는 필드가 SDK에서 실행되는 쿼리에 영향을 미친다는 것입니다.

EntityReferenceobject initializer에있는 속성에 액세스하는 중 문제가 발생하여 즉시 1 통화에서 속성에 액세스합니다. 설명 할 몇 가지 코드 - 아래의 문제 코드. 또한입니다 반환 된 데이터가 작은 있도록 쿼리 실행 만, 3 곳을 요구하기 때문에 매우 빠른 :

var results = allAccountsQuery.Select(account => new Account 
{ 
    AccountNo = account.GetAttributeValue<string>("AccountNumber"), 
    //AccountID NOT working! 
    AccountID = new EntityReference() { Id = account.GetAttributeValue<EntityReference>("AccountID").Id }.Id, 
    Name = account.GetAttributeValue<string>("AccountName") 
}).ToList(); 

기분을 상하게하는 라인은 다음과 같다 : 당신이 볼 수 있듯이

AccountID = new EntityReference() { Id = account.GetAttributeValue<EntityReference>("AccountID").Id }.Id 

, 난 을 시도하여 EntityReference의 인스턴스를 인스턴스화하고 초기화 한 다음 즉시 백 엔드의 속성에 액세스합니다. Object reference not set to an instance of an object

다음 코드는 작동하지만 매우 비효율적 인 이유는 모두가이되기 때문입니다. SDK는 object initiazlizer에 요청 된 필드를 기반으로 쿼리를 평가하기 위해서만 마술을 일부 수행합니다. 이 경우 쿼리가되고있는 평가하고 루프의 첫번째 반복에서 다시 모든을 제공하지만, 작동 :

List<Account> allAccounts = new List<Account>(); 
//Super slow - framework actually gets back ALL accounts in 1st iteration 
foreach (var account in allAccountsQuery) 
{ 
    Account newAccount = new Account 
    { 
    AccountNo = account.GetAttributeValue<string>("AccountNumber"), 
    Name = account.GetAttributeValue<string>("AccountName") 
    }; 

    //WORKS: This separate instantiation and then accessing of the property works!! 
    //Note it is done in 2 steps outside the object initializer 
    //Need to see if I can do this in an object initializer instead of separately 
    EntityReference ef = account.GetAttributeValue<EntityReference>("AccountID"); 
    newAccount.AccountID = ef.Id; 

    allAccounts.Add(newAccount); 
} 

그래서 질문은 내가 EntityReference 인스턴스를 지시하고 추출 할 수있는 방법은 재산 Id입니다 객체 이니셜 라이저에서 내 결과 평가 쿼리가 작습니까? 내가 한 이제

//Anonymous type collection 
var accounts = allAccountsQuery.Select(account => new 
{ 
    AccountNo = account.GetAttributeValue<string>("AccountNumber"), 
    AccountID = account.GetAttributeValue<EntityReference>("AccountID"), 
    Name = account.GetAttributeValue<string>("AccountName") 
}).ToList(); 

:

+1

nullref가 전달되는 이유는 무엇입니까? 그것은 전체 이니셜 라이저 일 수도 있고 단순히이 부분 일 수도 있습니다 :'account.GetAttributeValue ("AccountID"). Id'. 먼저 확인하십시오. –

+0

정의 된 코드를 제거하면 코드가 작동하고'results' 컬렉션이 채워지기 때문에 그 라인입니다. 그것이 문제가되는 재산입니다. – atconway

+0

그 줄에서'NullReference'를 얻는다면'foreach' 루프에서도 예외가 발생합니다, 그렇습니까? –

답변

0

지금까지 최고의 작동 내가 찾은 솔루션은 익명의 유형 컬렉션에 초기 데이터를로드 한 다음에 따라 실제 구체적인 유형 컬렉션을로드하는 것입니다 이 테스트하고있다

var results = accounts.Select(account => new Account 
{ 
    AccountNo = account.AccountNo, 
    AccountID = account.AccountID.Id, 
    Name = account.Name 
}).ToList(); 

: 더러운 일이 EntityReference 인스턴스가 나는 구체적인 유형을 채우기 .Id, 호텔에 액세스 할 수 있습니다, 정의하세요. results 컬렉션에는 실현 된 .Id 속성이 정의되어 있습니다. 그러나 알다시피 난 여전히 2 단계로해야만했다. 그러나 쿼리가 빠르게 실행되기 때문에 문제가 해결됩니다. 난 그냥 다음에 액세스하고 나중에 재산의 매핑 탱크를 잡고 일시적으로의 종류를 만들 수있는 경우에 나는 아직도이 솔루션은 긴 얻을 수 있기 때문에 1 개 개체 이니셜 라이저에서이 작업을 수행 할 수있는 개방적이야.

나는이 개체를 하나의 개체 초기화 프로그램에서로드하는 것을 선호합니다. 내가 제대로 이해했다면

0

당신은 CRM SDK와 대등 한 요청이

AccountSet.Select(account => new Account 
{ 
    AccountNumber = account.AccountNumber, 
    Id = account.Id, 
    Name = account.Name 
}) 

힌트가 될 것이다 다음 SQL 문

SELECT AccountNumber, Id, Name FROM Accounts 

비교 요청을 달성하고자하는 : Id 또는 AccountId는 Guid입니다. 이 아니라이고 EntityReference입니다.

따라서 account.GetAttributeValue<EntityReference>("AccountID")으로 전화하면 null이 반환됩니다. 따라서 Id 속성에 액세스하면 NullReference이 표시됩니다.

이 다음 QueryExpression

<?xml version="1.0" encoding="utf-8"?> 
<QueryExpression xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/xrm/2011/Contracts"> 
    <ColumnSet> 
    <AllColumns>false</AllColumns> 
    <Columns xmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays"> 
     <d3p1:string>accountnumber</d3p1:string> 
     <d3p1:string>name</d3p1:string> 
    </Columns> 
    </ColumnSet> 
    <Criteria> 
    <Conditions /> 
    <FilterOperator>And</FilterOperator> 
    <Filters /> 
    </Criteria> 
    <Distinct>false</Distinct> 
    <EntityName>account</EntityName> 
    <LinkEntities /> 
    <Orders /> 
    <PageInfo> 
    <Count>0</Count> 
    <PageNumber>1</PageNumber> 
    <PagingCookie i:nil="true" /> 
    <ReturnTotalRecordCount>false</ReturnTotalRecordCount> 
    </PageInfo> 
    <NoLock>false</NoLock> 
</QueryExpression> 

그래서 단지이 세 가지 속성이

+0

"사용자 ID 또는 계정 ID가 GUID 일 뿐이며 EntityReference가 아닙니다"라는 주석이 사실이 아닙니다. 텍스트 파일에 쓰거나 디버깅하는 동안 직접 검사하면, 사용중인 필드가'EntityReference' 유형인지 알 수 있습니다. 살펴보기 :'key : 'AccountID'value : 'Microsoft.Xrm.Sdk.EntityReference'' 당신이 보여준 것은 이미 모든 간단한 유형 (문자열, int 등)에 대해 사실 인 것을 알고 있었지만 필연적으로 필자는 (여기를 포함해서)'EntityReference' 속성을 가지고 있고, 나는 하나의 객체 초기화 자 안에 그것의 속성 중 하나를 캐스팅하고 접근하는 방법을 찾지 못했습니다. – atconway

+0

@atconway : 표준 Account 엔티티에 대해 말하는 것이고 AccountId 속성을 확실히 의미합니까? – ccellar

+0

거기에 맞지 않습니다. 전형적인 SO 게시물과 마찬가지로 필자는 일부 필드 이름을 '이해하기 어렵습니다'. 최종선 - 내가 접근하는 속성은'Microsoft.Xrm.Sdk.EntityReference' 유형입니다. 이것은 정말로 'C#'질문이며 'CRM'방법이 아닙니다. 그것은 객체 이니셜 라이저에서 인스턴스 속성의 필드에 직접 액세스하는 방법에 대한 일반적인 질문입니다 (실제로는 _any_ .NET 인스턴스 객체에 해당됩니다). 나는 (1) 단계가 아니라 (2) 단계로 그것을 할 수있다. – atconway

0

내가 솔루션에 어떤 문제가 있는지 확실하지 않다하지만 난 확신 결과에 요청하고 포함 된 결과 쿼리 식의 열을 제한하고 .ToEntity <> 메서드를 사용하여 컬렉션을 계정으로 전송하려고합니다.

QueryExpression query = new QueryExpression("account"); 
query.ColumnSet = new ColumnSet(new string[] { "AccountId", "AccountNumber", "AccountName" }); 
List<Account> allAccounts = service.RetrieveMultiple(query).Entities.Select(account => account.ToEntity<Account>()).ToList<Account>(); 
+0

나는 실제로 당신과 다른 접근법을 사용하고 있습니다. 귀하의 솔루션은 초기 바인딩 된 엔티티를 사용하며, 늦은 바운드를 사용하고 있습니다 (초기 바인딩 엔티티를 생성하고 해킹 솔루션을 수행하지 않기 위해 CRM 2011 SDK에 대한 VS2013 지원이 없음). 또한 LINQ/Expression 구문을 사용하여 내 표현식이 'ColumnSet' 및'RetrieveMultiple' 호출과 동일한 작업을 수행해야하는 것을 통해 열을 제한합니다. 'SDK '를 사용하면 데이터를 가져올 수있는 몇 가지 방법이 있습니다. 내 OP가 잘 이해되지 않고 있다고 생각합니다. 사실 나는 1 회 객체 이니셜 라이저 접근법을 찾고있는 솔루션을 게시했습니다. – atconway

+0

내 솔루션을 크게 변경하지 않고 후기 바인딩 모델로 변환 할 수 있습니다. 그러나 두 번째로 보았을 때 나는 우리의 코드가 CRM을 쿼리하는 방식이 크게 다를 수 있다는 것에 동의합니다. allAccountsQuery는 DataCollection 또는 유사한 개체라고 가정했지만 사용자 의견에서 볼 때 완전히 다른 것으로 보입니다. LINQ의 사용은 꽤 흥미 롭습니다. 이전에는 노출되지 않았지만 쿼리하는 방법을 설명하는 몇 가지 리소스가 있습니까? – Zach

+0

예 - 다음 링크 및 리소스를 살펴보십시오. http://msdn.microsoft.com/en-us/library/gg328028.aspx 'LINQ'를 통해 'CRM'을 쿼리하는 방법에 대한 정보가 있습니다. '람다 '. – atconway

관련 문제