QuerySpec: Model fields not being populated

Posts   
 
    
jovball
User
Posts: 434
Joined: 23-Jan-2005
# Posted on: 12-Feb-2017 22:38:56   

I've stumbled across a situation where some fields in my model are not being populated. It has something to do with the order of fields in the query.

Here is the repro example for Northwind.



    public class OrderModel
    {
        [Display(Name = "Order Id")]
        public int OrderId { get; set; }

        [Display(Name = "Customer Id")]
        public string CustomerId { get; set; }

        [Display(Name = "Company Name")]
        public string CompanyName { get; set; }

        [Display(Name = "Employee Id")]
        public int? EmployeeId { get; set; }

        [Display(Name = "Order Date")]
        public DateTime? OrderDate { get; set; }

        [Display(Name = "Required Date")]
        public DateTime? RequiredDate { get; set; }

        [Display(Name = "ShippedDate")]
        public DateTime? ShippedDate { get; set; }

        [Display(Name = "Freight")]
        public decimal? Freight { get; set; }

        [Display(Name ="Ship Name")]
        public string ShipName { get; set; }

        [Display(Name = "Ship Address")]
        public string ShipAddress { get; set; }

        [Display(Name = "Ship City")]
        public string ShipCity { get; set; }

        [Display(Name = "Ship Region")]
        public string ShipRegion { get; set; }

        [Display(Name = "Ship Postal Code")]
        public string ShipPostalCode { get; set; }

        [Display(Name = "Ship Country")]
        public string ShipCountry { get; set; }

    }


The first QuerySpec query below will populate the CompanyName field and the second will not. The only difference between them is the position of CustomerFields.CompanyName in the query.


var query = qf.Create()
                .From(qf.Customer
                .InnerJoin(qf.Order)
                .On(CustomerFields.CustomerId == OrderFields.CustomerId))

                .Select<OrderModel>(OrderFields.OrderId, OrderFields.OrderDate, OrderFields.RequiredDate,
                    OrderFields.ShippedDate, OrderFields.CustomerId, CustomerFields.CompanyName,
                    OrderFields.EmployeeId, OrderFields.Freight,
                    OrderFields.ShipCity, OrderFields.ShipRegion,
                    OrderFields.ShipCountry, OrderFields.ShipVia)
                 .OrderBy(OrderFields.OrderDate.Descending());

            var items = new List<OrderModel>();
            using (var dataAdapter = new DataAccessAdapter())
            {
                items = dataAdapter.FetchQuery<OrderModel>(query);
            }


var query = qf.Create()
                .From(qf.Customer
                .InnerJoin(qf.Order)
                .On(CustomerFields.CustomerId == OrderFields.CustomerId))

                .Select<OrderModel>(OrderFields.OrderId, OrderFields.OrderDate, OrderFields.RequiredDate,
                    OrderFields.ShippedDate, OrderFields.CustomerId,
                    OrderFields.EmployeeId, OrderFields.Freight,
                    OrderFields.ShipCity, OrderFields.ShipRegion,
                    OrderFields.ShipCountry, OrderFields.ShipVia, CustomerFields.CompanyName)
                 .OrderBy(OrderFields.OrderDate.Descending());

            var items = new List<OrderModel>();
            using (var dataAdapter = new DataAccessAdapter())
            {
                items = dataAdapter.FetchQuery<OrderModel>(query);
            }

I'm using the 5.1.2 runtime but the same issue exists for 5.1.1 as well.

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 13-Feb-2017 05:38:27   

OrderModel class is generated by LLBLGen? The probles is that in the second query, all the fields are populated except CompanyName, Right? About the GeneratedSql I assume it's the same in both cases. Is that so?

David Elizondo | LLBLGen Support Team
jovball
User
Posts: 434
Joined: 23-Jan-2005
# Posted on: 16-Feb-2017 02:57:12   

The OrderModel class is hand-coded.

I spent more time debugging this and have some additional information on the problem. First, the actual query is always generated correctly. The issue is with populating the model fields.

In this case, OrderFields.ShipVia is in the query but not in the model. If ShipVia is the last field in the query, everything is fine.

If ShipVia is in any other position, things get strange. It appears to me as though LLBLGen somehow skips a column in the query and incorrectly assigns values from that point.

Given fields in this order in the query, ShipVia, ShipCity, ShipRegion, ShipCountry for Order ID 10250, the model values should be this

ShipCity: Rio de Janeiro ShipRegion: RJ ShipCountry: Brazil

Instead they are this:

Ship City: (null) Ship Region Rio de Janeiro Ship Country RJ

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 16-Feb-2017 07:02:59   

Could you please show us your OrderModel class? I think maybe there is the problem.

Another thing you could do is use the lambda variant. See the docs for more info

David Elizondo | LLBLGen Support Team
jovball
User
Posts: 434
Joined: 23-Jan-2005
# Posted on: 16-Feb-2017 13:38:00   

I already included the model at the start of my first post.

Also, I don't understand why you're pointing me to the docs. I'm not having any trouble understanding how to use LLBLGen.

Obviously, I could and should fix my query. However, this situation is going to happen in real life. I'm pointing out an edge case that gives unexpected results. IMO, this is a bug.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39590
Joined: 17-Aug-2003
# Posted on: 17-Feb-2017 17:32:32   

It's odd this happens, as the fields in the projection is leading for the projection list. Looks like a bug indeed. We'll look into it.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39590
Joined: 17-Aug-2003
# Posted on: 20-Feb-2017 10:35:25   

Reproduced. Looking into it.

Problem is caused by the lambda projection generated from the type (the ()=> new OrderModel() { OrderId = <field>.ToValue<int32>(), ... }): that lambda is then handled and it's assumed the fields in the lambda are the ones in the query (as that was normally the case: a projection lambda only took into account the fields with ToValue<>() calls), and it simply fetches by ordinal. This goes wrong as the real projection of the query is defined by a different set of fields.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39590
Joined: 17-Aug-2003
# Posted on: 20-Feb-2017 12:19:47   

Fixed in next build. (5.1.3 hotfix, released later today)

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39590
Joined: 17-Aug-2003
# Posted on: 20-Feb-2017 16:42:57   

v5.1.3 hotfix build is now available (on the site and the runtimes are also available as prerelease on nuget)

Frans Bouma | Lead developer LLBLGen Pro
jovball
User
Posts: 434
Joined: 23-Jan-2005
# Posted on: 20-Feb-2017 18:03:08   

I confirm that this is fixed for me with v5.1.3. Thanks as always for the quick customer support. Again and again, your customer support is an important product feature for me.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39590
Joined: 17-Aug-2003
# Posted on: 21-Feb-2017 10:10:00   

Thanks Joel simple_smile Glad it's sorted simple_smile

Frans Bouma | Lead developer LLBLGen Pro