Left outer join gives error message 'Unable to cast the type 'System.Nullable`1' to type 'System.Object'.'

StackOverflow https://stackoverflow.com/questions/22356780

  •  13-06-2023
  •  | 
  •  

This is driving me nuts!

I have tried a number of ways (and many iterations of each way) but get the same error.

I have tried the query in LINQPad and get the desired result.

Scenario: A marina. I want a list of all the slips with boat details, if a boat is registered as staying at the slip. If there is no boat registered at a slip then the boatID field could be NULL (I know this should be set up as a key but I am trying to use Linq to get to the answer without changing the data base). There is a 'Slip' table with a list of slips, including a BoatId field (for when a boat is registered at the slip). The second table is a 'Boat' table, with BoatId as the key and other boat details.

Here is a SQL Query (that produces the result I want):

Select s.SlipID, s.SlipNumber, s.Length, s.Electricity, s.Telephone, s.TV,
b.BoatName+' ['+b.BoatType+', '+convert(varchar,b.BoatOverAllLength)+']' as boatDets, 
s.Status 
from Slip as s left outer join boat as b on s.BoatID = b.BoatId;

Here is one of the solutions that gives an error (but works in LINQPad):

var slipDets6 = from s6 in db.Slips
                join b6 in db.Boats on s6.BoatId equals b6.BoatId into temp
                from jn in temp.DefaultIfEmpty()
                orderby s6.SlipNumber 
                select new 
                { 
                    SlipID = (int?) s6.SlipId, 
                    SlipNumber = s6.SlipNumber, 
                    Length = s6.Length, 
                    Electricity = s6.Electricity, 
                    Telephone = s6.Telephone, 
                    TV = s6.TV, 
                    BoatDets = jn.BoatName + " [" + jn.BoatType + ", " + jn.BoatOverAllLength + "]", 
                    Status = s6.Status 
                };

The actual error code I receive is:

Unable to cast the type System.Nullable'1 to type System.Object. LINQ to Entities only supports casting EDM primitive or enumeration types.

I have delved into as many solutions I could find on this site (and others) but I seem to be doing the right thing.

有帮助吗?

解决方案

according to your comment, the problem is where u try to create a string from BoatName, BoatType and BoatOverAllLength, you cant format a string in linq to entities, as i said before (prev post, no3), you can fetch data you need and then select in memory to create BoatDets string, so this, surely works:

var slipDets6 = (from s6 in db.Slips
             join b6 in db.Boats on s6.BoatId equals b6.BoatId into temp
             from jn in temp.DefaultIfEmpty()
             orderby s6.SlipNumber
             select new {s6, jn})
             .ToList()
             .Select(u => new
                 {
                     SlipID = (int?)u.s6.SlipId,
                     SlipNumber = u.s6.SlipNumber,
                     Length = u.s6.Length,
                     Electricity = u.s6.Electricity,
                     Telephone = u.s6.Telephone,
                     TV = u.s6.TV,
                     BoatDets = u.jn == null ? "" : u.jn.BoatName + " [" + u.jn.BoatType + ", " + u.jn.BoatOverAllLength + "]",
                     Status = u.s6.Status
                 })
             .ToList();

or, you can fetch BoatName, BoatType and BoatOverAllLength as property, and when your query fetched, create string you need from that properties, something like this:

public class FlatSlip
    {
        public int? SlipID { get; set; }
        public string SlipNumber { get; set; }
        public string Length { get; set; }
        public string Electricity { get; set; }
        public string Telephone { get; set; }
        public string TV { get; set; }
        public string BoatName { get; set; }
        public string BoatType { get; set; }
        public string BoatOverAllLength { get; set; }
        public string Status { get; set; }

        public string BoatDets
        {
            get
            {
                return this.BoatName + " [" + this.BoatType + ", " + this.BoatOverAllLength + "]";
            }
        }
    }

var slipDets6 = from s6 in db.Slips
                        join b6 in db.Boats on s6.BoatId equals b6.BoatId into temp
                        from jn in temp.DefaultIfEmpty()
                        orderby s6.SlipNumber
                        select new FlatSlip()
                        {
                            SlipID = (int?)s6.SlipId,
                            SlipNumber = s6.SlipNumber,
                            Length = s6.Length,
                            Electricity = s6.Electricity,
                            Telephone = s6.Telephone,
                            TV = s6.TV,
                            BoatName = jn == null ? "" : jn.BoatName,
                            BoatType = jn == null ? "" : jn.BoatType,
                            BoatOverAllLength = jn == null ? "" : jn.BoatOverAllLength,
                            Status = s6.Status
                        };

or if you are insisting on using literal:

public class Boat
    {
        public Boat()
        {
        }

        public Boat(string BoatName, string BoatType, string BoatOverAllLength)
        {
            this.BoatName = BoatName;
            this.BoatType = BoatType;
            this.BoatOverAllLength = BoatOverAllLength;
        }

        public string BoatName { get; set; }
        public string BoatType { get; set; }
        public string BoatOverAllLength { get; set; }

        public string BoatDets
        {
            get
            {
                return this.BoatName + " [" + this.BoatType + ", " + this.BoatOverAllLength + "]";
            }
        }
    }

        var slipDets6 = (from s6 in db.Slips
                         join b6 in db.Boats on s6.BoatId equals b6.BoatId into temp
                         from jn in temp.DefaultIfEmpty()
                         orderby s6.SlipNumber
                         select new { s6, jn })
                         .ToList()
                         .Select(u => new
                         {
                             SlipID = (int?)u.s6.SlipId,
                             SlipNumber = u.s6.SlipNumber,
                             Length = u.s6.Length,
                             Electricity = u.s6.Electricity,
                             Telephone = u.s6.Telephone,
                             TV = u.s6.TV,
                             BoatDets = jn == null ? new Boat() : new Boat(u.jn.BoatName, u.jn.BoatType, u.jn.BoatOverAllLength),
                             Status = u.s6.Status
                         })
                         .ToList();

notice: BoatDets property, in my two last queries, can not be used in linq to entity, and its readable when your data has been fetched to memory

其他提示

1- in .netframework4 you cant use enumerations in linq to entities, but in .netframework4.5 you can, and in .netframework4 when you use enumeration this exception occurs, although i dont see any enumeration in your codes...

2- you can comment properties in your select one by one, to find the property causing exception, and check its type...

3- probably you will not any problem, if fetch data before select them as a literal like this:

var slipDets6 = (from s6 in db.Slips
                 join b6 in db.Boats on s6.BoatId equals b6.BoatId into temp
                 from jn in temp.DefaultIfEmpty()
                 orderby s6.SlipNumber
                 select new {s6, jn})
                 .ToList()
                 .Select(u => new
                     {
                         SlipID = (int?)u.s6.SlipId,
                         SlipNumber = u.s6.SlipNumber,
                         Length = u.s6.Length,
                         Electricity = u.s6.Electricity,
                         Telephone = u.s6.Telephone,
                         TV = u.s6.TV,
                         BoatDets = u.jn.BoatName + " [" + u.jn.BoatType + ", " + u.jn.BoatOverAllLength + "]",
                         Status = u.s6.Status
                     })
                 .ToList();

4- be careful, if jn be null, this line BoatDets = u.jn.BoatName + " [" + u.jn.BoatType + ", " + u.jn.BoatOverAllLength + "]", is causing an exception

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top