1

I want to change all my queries from QueryExpression to Linq. In development time, all seems to be just fine, but I always get a cast exception at runtime (can't cast Microsoft.xrm.sdk.entity to Xrm.SystemUser -> Xrm is the early bound classes generated with CrmSvcUtil).

        var context = new OrganizationServiceContext(crmService);
        SystemUser x = (from c in context.CreateQuery<SystemUser>()
                where c.DomainName == @"pfgc\" + Environment.UserName
                select c).FirstOrDefault();

This code is straightforward. I've even tried without the Where clause and it won't change anything.

I tried the following (no FirstOrDefault and var instead of SystemUser)

            var x = (from c in context.CreateQuery<SystemUser>()
                where c.DomainName == @"pfgc\" + Environment.UserName
                select c);

This won't throw an exception but x type is Microsoft.xrm.sdk.linq.Query. What am I doing wrong? It seems to be exactly what the SDK suggests to do.

EDIT:

GCATNM has the right answer. In case someone faces the same issue, here's a sample of the working code:

    public SystemUser GetCurrentUser()
    {
        var context = GetOrgContext();
        return (from c in context.CreateQuery<SystemUser>()
                where c.DomainName == @"pfgc\" + Environment.UserName
                select c).FirstOrDefault();
    }

    public OrganizationServiceContext GetOrgContext()
    {
        var serviceProxy1 = new OrganizationServiceProxy(organizationUri, homeRealmUri, credentials, null);
        serviceProxy1.ServiceConfiguration.CurrentServiceEndpoint.Behaviors.Add(new ProxyTypesBehavior());
        return new OrganizationServiceContext(serviceProxy1);
    }
Mathieu
  • 4,449
  • 7
  • 41
  • 60

2 Answers2

4

I had a similar problem with LINQ-to-CRM and went back to QueryExpressions because they worked, until I found the solution in some SDK sample while looking for something else: You need to add a ProxyTypesBehavior to your IOrganizationService object. I don't know what it does, but that definitely was the change that allowed me to use LINQ with the early bound classes (as I perceive it, LINQ-to-CRM can only be used with the early bound classes).

So the line you need after creating your IOrganizationService is:

organizationService.ServiceConfiguration.CurrentServiceEndpoint.Behaviors.Add(new ProxyTypesBehavior());

I hope that helps.

TeaDrivenDev
  • 6,591
  • 33
  • 50
  • This IS the solution. I was looking at the wrong place! Thank you very much! – Mathieu Mar 22 '11 at 14:43
  • 3
    Yes but you could use this : svcOrg.EnableProxyTypes() ;-) – Coolweb Apr 22 '11 at 07:09
  • @Coolweb: Indeed, but I didn't know that then. ;-) – TeaDrivenDev Apr 24 '11 at 15:18
  • Also worth noting that You must call the "Dispose" method on the proxy directly if you do not use a "using" statement in your code when creating the proxy instance. – Mark Jun 21 '11 at 22:43
  • 1
    ServiceConfiguration does not exist as a property on IOrganizationService, but on OrganizationServiceProxy. How can this work ? – Matt Jun 27 '11 at 09:09
0

It returns an Entity object, so you'll need to call ToEntity() if you want a System User object. The following should work for you:

var context = new OrganizationServiceContext(crmService);
    SystemUser x = (from c in context.CreateQuery<SystemUser>()
            where (string)c["DomainName"] == @"pfgc\" + Environment.UserName
            select c).FirstOrDefault().ToEntity<SystemUser>();
Michael M
  • 398
  • 1
  • 4
  • Thank you for your answer. But it returns the same exception unfortunatly. – Mathieu Mar 21 '11 at 03:22
  • I've updated the code sample. The invalid cast exception was probably occurring in the where clause. – Michael M Mar 21 '11 at 04:04
  • It doesn't change anything. Even without the Where clause, it returns the same exception. Maybe early bound can't be used with Linq To CRM? – Mathieu Mar 21 '11 at 12:51