ObjectDataSource bound to join doesn't populate fully

Posts   
 
    
webbsk
User
Posts: 17
Joined: 24-Sep-2009
# Posted on: 20-Oct-2011 19:42:34   

I have the following query in my business layer:


IQueryable<DomainsEntity> query = (
   from d in metaData.Domains join e in metaData.ExternalIps
   on d.ExternalIpId equals e.Id
   select d
   ).TakePage(pageNumber, maximumRows).Sort<DomainsEntity>(sortExpression);

EntityCollection<DomainsEntity> domains = ((ILLBLGenProQuery)query).Execute<EntityCollection<DomainsEntity>>();

The Domains collection is then bound to an ObjectDataSource. However, I can't seem to access the data from e.

I have tried subclassing DomainsEntity into DomainsEntity and adding the ExternalIp address to it, but when I try to execute the following query:

public class CustomizedDomain : DomainsEntity
{
     public string ExternalIpAddress;
}

....

IQueryable<CustomizedDomain> query = (
                                                         from d in metaData.Domains
                                                         join e in metaData.ExternalIps
                                                             on d.ExternalIpId equals e.Id
                                                         select new CustomizedDomain { Id = d.Id, MerchantId = d.MerchantId, PrivateLabelId = d.PrivateLabelId, Domain = d.Domain, IsValid = d.IsValid, Notes = d.Notes, ExternalIpAddress = e.IpAddress, HasSslCert = d.HasSslCert }
                                                     ).TakePage(pageNumber, maximumRows).Sort<CustomizedDomain>(sortExpression);

                domains = ((ILLBLGenProQuery)query).Execute<EntityCollection<CustomizedDomain>>();

I get the following error:

Unable to cast object of type 'OneShop.Operations.DAL.HelperClasses.EntityCollection1[OneShop.Operations.DAL.EntityClasses.DomainsEntity]' to type 'System.Collections.Generic.IList1[OneShop.Operations.Business.Hosting.CustomizedDomain]'.

Any ideas?

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 20-Oct-2011 22:17:54   

You dont need to subclass the entity. Please show us how are you bounding it to the ObjectDataSource. Btw, What you didn't use LLBLGenProDatasource?

David Elizondo | LLBLGen Support Team
webbsk
User
Posts: 17
Joined: 24-Sep-2009
# Posted on: 21-Oct-2011 17:58:16   

The one example that I have of being able to use an ObjectDataSource with a join is by creating a POCO that is basically all the fields I want. For example,

public class CustomizedDomain
{
        public int Id { get; set; }
        public int MerchantId { get; set; }
        public int PrivateLabelId { get; set; }
        public string Domain { get; set; }
        public bool IsValid { get; set; }
        public string Notes { get; set; }
        public string ExternalIpAddress { get; set; }
        public bool HasSslCert { get; set; }
}

When I use this in combination with the previous code, it works fine. However, if I try to have CustomizedDomain inherit from DomainEntity and just add the extra field I need, it won't work anymore and I get the same error message.

public class CustomizedDomain : DomainsEntity
{
        public string ExternalIpAddress { get; set; }
}

I don't understand why that is - does it have something to do with reflection?

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 21-Oct-2011 19:30:47   

I think it has to do with a missing explicit conversion at this point:

 domains = ((ILLBLGenProQuery)query).Execute<EntityCollection<CustomizedDomain>>();

What is the type of 'domains' variable? And.. the errors comes from that line? Because you mentioned 'ObjectDataSource' so I don't know if the problem is at databinding.

David Elizondo | LLBLGen Support Team
webbsk
User
Posts: 17
Joined: 24-Sep-2009
# Posted on: 21-Oct-2011 20:23:30   

I've tried just letting it come back as var so that it will dynamically type itself. That doesn't seem to be the problem. It dies on that line before it tries to assign to the domains variable.

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 21-Oct-2011 20:54:09   

I see now, the problem is at the linq query:

IQueryable<CustomizedDomain> query = (
                                                         from d in metaData.Domains
                                                         join e in metaData.ExternalIps
                                                             on d.ExternalIpId equals e.Id
                                                         select new CustomizedDomain { Id = d.Id, MerchantId = d.MerchantId, PrivateLabelId = d.PrivateLabelId, Domain = d.Domain, IsValid = d.IsValid, Notes = d.Notes, ExternalIpAddress = e.IpAddress, HasSslCert = d.HasSslCert }
                                                     ).TakePage(pageNumber, maximumRows).Sort<CustomizedDomain>(sortExpression);

There is no metaData information for CustomizedDomain, so I think the problem in at the Sort routine. You can confirm that excluding the Sort and maybe the TakePage operators. To overcome this you could try executing the query without Sort then sort the result in-memory.

I'm not sure, but I think that if you move the sort inside the query that would avoid the projection problem:

IQueryable<CustomizedDomain> query = (
                                                         from d in metaData.Domains
                                                         join e in metaData.ExternalIps
                                                             on d.ExternalIpId equals e.Id
                                                         orderby d.SomeField
                                                         select new CustomizedDomain { Id = d.Id, MerchantId = d.MerchantId, PrivateLabelId = d.PrivateLabelId, Domain = d.Domain, IsValid = d.IsValid, Notes = d.Notes, ExternalIpAddress = e.IpAddress, HasSslCert = d.HasSslCert }
                                                     ).TakePage(pageNumber, maximumRows);

Another thing you can do is add a your custom property directly on a partial class of DomainEntity instead of create a subclass.

David Elizondo | LLBLGen Support Team
webbsk
User
Posts: 17
Joined: 24-Sep-2009
# Posted on: 21-Oct-2011 23:10:02   

I have tried that actually and just called it with a ToList() method. It is still them same error.

I also considered adding to the entity by using a partial class, but I don't want to do that because I use the class in other places and I don't need the extra field there.

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 22-Oct-2011 10:43:21   

I reproduce it. The problem, I think, is that the destination object for the projection is always DomainEntity because CustomizedDomain inherits from it and DomainEntity has linq metadata information. I workaround I found is that you first fetch an anonymous type, then use it to project in-memory to a CustomizedDomain list. Something like this:

var results = (
     from d in metaData.Domains
     join e in metaData.ExternalIps on d.ExternalIpId equals e.Id
     sortby d.SomeField
     select new
     { 
          Id = d.Id, 
          MerchantId = d.MerchantId, 
          PrivateLabelId = d.PrivateLabelId, 
          Domain = d.Domain, 
          IsValid = d.IsValid, 
          Notes = d.Notes, 
          ExternalIpAddress = e.IpAddress, 
          HasSslCert = d.HasSslCert 
     })
     .TakePage(pageNumber, maximumRows)
     .ToList();

List<CustomizedDomain> domains = (
     from x in results
     select new CustomizedDomain
     { 
          Id = x.Id, 
          MerchantId = x.MerchantId, 
          PrivateLabelId = x.PrivateLabelId, 
          Domain = x.Domain, 
          IsValid = x.IsValid, 
          Notes = x.Notes, 
          ExternalIpAddress = x.IpAddress, 
          HasSslCert = x.HasSslCert 
     })
     .ToList();

Let me know if that worked for you.

David Elizondo | LLBLGen Support Team