Entities inside of Projections

Posts   
 
    
JRR avatar
JRR
User
Posts: 125
Joined: 07-Dec-2005
# Posted on: 03-Oct-2011 19:55:05   

I have a question regarding projections. I assume and understand from my reading that returning an entity inside of a projection is not supported by the llblgen linq query engine, but would like confirmation.

Here is code in my business layer. I have two methods: one to retrieve calculations for each entity, and the other to fetch entities.

Here is my wrapper class


    public class VendorDistance
    {
        public int VendorId { get; set; }
        public float DistanceInKm { get; set; }
        public VendorEntity Vendor { get; set; }
    }

And I have a Vendor Manager class with a 2 important methods - containing seperate queries A and B. _ (Note: the DataSource object is LinqMetaData.Vendor)_


      public IQueryable<VendorDistance> GetVendorsWithinDistanceOfPostalCode(string postalCode, float meters, Func<string, PostalCodeEntity> findPostalCodeFunc)
        {
            var postalCodeEntity = GetPostalCode(postalCode, findPostalCodeFunc);

            // query A: Query Distances For Vendors
            var q2 = from vendorEntity in DataSource
                     let distance = vendorEntity.Latitidue.HasValue && vendorEntity.Longitude.HasValue
                                        ? Functions.GetDistanceInKilometers((float) postalCodeEntity.Longitude,
                                                                            (float) postalCodeEntity.Latitude, (float) vendorEntity.Longitude,
                                                                            (float) vendorEntity.Latitidue)
                                        : -1
                     where distance > 0
                     orderby distance
                     select new VendorDistance { DistanceInKm = distance, VendorId = vendorEntity.VendorId };

            return q2;

        }

        public void SetVendorInstances(IList<VendorDistance> input)
        {
            var ids = input.Select(a => a.VendorId);

            // query B: Get Vendors
            var entities = (from vendorEntity in DataSource
                            where ids.Contains(vendorEntity.VendorId)
                            select vendorEntity).ToList();

            var joined = from entity in entities
                         join i in input on entity.VendorId equals i.VendorId
                         select new { entity, i };

            joined.ToList().ForEach(a => a.i.Vendor = a.entity);
        }

I am using query A and query B because my first approach of query Z did not work:


        public IQueryable<VendorDistance> GetVendorsWithinDistanceOfPostalCode(string postalCode, float meters, Func<string, PostalCodeEntity> findPostalCodeFunc)
        {
            var postalCodeEntity = GetPostalCode(postalCode, findPostalCodeFunc);

            // query Z: Query Distances For Vendors AND Vendors at the same time.
            var q2 = from vendorEntity in DataSource
                     let distance = vendorEntity.Latitidue.HasValue && vendorEntity.Longitude.HasValue
                                        ? Functions.GetDistanceInKilometers((float) postalCodeEntity.Longitude,
                                                                            (float) postalCodeEntity.Latitude, (float) vendorEntity.Longitude,
                                                                            (float) vendorEntity.Latitidue)
                                        : -1
                     where distance > 0
                     orderby distance
                     select new VendorDistance { DistanceInKm = distance, Vendor = vendorEntity };

            return q2;

        }

As you can see in this scenario, I am setting the Vendor instance inside of the original linq query that is performing the query for the distance, but I assume this is not possible.

The generated sql is good, but I get this exception:

Test method AN.SF.Addons.Tests.DistanceTests.HI threw exception: System.FormatException: Input string was not in a correct format. at System.Number.ParseSingle(String value, NumberStyles options, NumberFormatInfo numfmt) at System.Convert.ToSingle(String value, IFormatProvider provider) at System.String.System.IConvertible.ToSingle(IFormatProvider provider) at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider) at System.Convert.ChangeType(Object value, Type conversionType) at lambda_method(Closure, Object[], Int32[]) at SD.LLBLGen.Pro.LinqSupportClasses.DataProjectorToObjectList1. AddRowToResults(IList projectors, Object[] rawProjectionResult) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\DataProjectorToObjectList.cs: line 114 at SD.LLBLGen.Pro.LinqSupportClasses.DataProjectorToObjectList1. SD.LLBLGen.Pro.ORMSupportClasses.IGeneralDataProjector.AddProjectionResultToContainer(List1 valueProjectors, Object[] rawProjectionResult) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\DataProjectorToObjectList.cs: line 99 at SD.LLBLGen.Pro.ORMSupportClasses.ProjectionUtils.FetchProjectionFromReader(List1 valueProjectors, IGeneralDataProjector projector, IDataReader datasource, Int32 maxNumberOfItemsToReturn, Int32 pageNumber, Int32 pageSize, Boolean clientSideLimitation, Boolean clientSideDistinctFiltering, Boolean clientSidePaging, UniqueList1 stringCache, Dictionary2 typeConvertersToRun) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\ORMSupportClasses\Projection\ProjectionUtils.cs: line 202 at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.FetchProjection(List1 valueProjectors, IGeneralDataProjector projector, IRetrievalQuery queryToExecute, Dictionary2 typeConvertersToRun) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\ORMSupportClasses\AdapterSpecific\DataAccessAdapterBase.cs: line 1711 at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.FetchProjection(List1 valueProjectors, IGeneralDataProjector projector, IEntityFields2 fields, IRelationPredicateBucket filter, Int32 maxNumberOfItemsToReturn, ISortExpression sortClauses, IGroupByCollection groupByClause, Boolean allowDuplicates, Int32 pageNumber, Int32 pageSize) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\ORMSupportClasses\AdapterSpecific\DataAccessAdapterBase.cs: line 1671 at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProvider2.ExecuteValueListProjection(QueryExpression toExecute) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\LLBLGenProProvider2.cs: line 179 at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.ExecuteExpression(Expression handledExpression) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\LLBLGenProProviderBase.cs: line 264 at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.Execute(Expression expression) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\LLBLGenProProviderBase.cs: line 93 at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.System.Linq.IQueryProvider.Execute(Expression expression) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\LLBLGenProProviderBase.cs: line 697 at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProQuery1.System.Collections.Generic.IEnumerable<T>.GetEnumerator() in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\LLBLGenProQuery.cs: line 162 at System.Collections.Generic.List1..ctor(IEnumerable1 collection) at System.Linq.Enumerable.ToList(IEnumerable`1 source) at AN.SF.Addons.Tests.DistanceTests.HI() in DistanceTests.cs: line 40

So in closing, it seems that queries A&B are supported, while query Z is not supported. Can someone please confirm?

LLBLGen 3.1 vJune 17th, 2011

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 04-Oct-2011 05:24:31   

You can't assign it that way. You need to create the projection manually, that is: specify the properties to be set. Example:

 var q2 = from vendorEntity in DataSource
                     let distance = vendorEntity.Latitidue.HasValue && vendorEntity.Longitude.HasValue
                                        ? Functions.GetDistanceInKilometers((float) postalCodeEntity.Longitude,
                                                                            (float) postalCodeEntity.Latitude, (float) vendorEntity.Longitude,
                                                                            (float) vendorEntity.Latitidue)
                                        : -1
                     where distance > 0
                     orderby distance
                     select new VendorDistance 
                    { 
                            DistanceInKm = distance, 
                            Vendor = new VendorEntity 
                           {
                                 VendorId = vendorEntity.VendorId,
                                 AnotherVendorField = vendorEntity.AnotherVendorField,
                                 // .... so on
                           }
                      };

            return q2;

Related threads: http://llblgen.com/tinyforum/Messages.aspx?ThreadID=15133 http://llblgen.com/tinyforum/Messages.aspx?ThreadID=14390 http://llblgen.com/tinyforum/Messages.aspx?ThreadID=15212

David Elizondo | LLBLGen Support Team
JRR avatar
JRR
User
Posts: 125
Joined: 07-Dec-2005
# Posted on: 04-Oct-2011 06:03:37   

Thanks David,

I was pretty sure of that, just wanted that confirmed.