Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot convert implicitly a type 'System.Linq.IQueryable' into 'Microsoft.EntityFrameworkCore.Query.IIncludableQueryable'

Tags:

c#

asp.net

linq

When I am developing my ASP.Net App, the following error was displayed.

Error CS0266
Cannot convert implicitly a type 'System.Linq.IQueryable' into 'Microsoft.EntityFrameworkCore.Query.IIncludableQueryable' There is an explicit conversion (check if you lack a cast) urlapp12 C:\Users\mjkpt\source\repos\teststage\urlapp12\urlapp12\Controllers\TagsController.cs 37 active

The captured screenshot of the error

t.Urlid and Urlid are both int.

The code including the error is the following:

        //int id, [Bind("BlogId,Userid,Url,Title")] Blog blog
        // GET: Tags
//        public async Task<IActionResult> Index()
        public async Task<IActionResult> Index(int id, [Bind("Urlid,Userid,UrlStr,Title")] Url blog, int Urlid)
        {
            /*
            return View(await _context.Tag.ToListAsync());
            */
            var blogging02Context = _context.Tag.Include(t => t.Blog);

            if (!string.IsNullOrEmpty(Urlid.ToString()))
            {
                blogging02Context = blogging02Context.Where(t => t.Urlid == Urlid);
            }

            ViewBag.Urlid = Urlid;
            return View(await blogging02Context.ToListAsync());

//            return View (await _context.Tag.ToListAsync());
        }

The Url model Url.cs is the following:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace urlapp12.Models
{
    public partial class Url
    {
        public Url()
        {
            Post = new HashSet<Post>();
        }

        [Key]
        public int Urlid { get; set; }
        public string UserId { get; set; }
        public string UrlStr { get; set; }
        public string Title { get; set; }

        public string CreatedBy { get; set; }
        public string CreatedBy_UserName { get; set; }
        [System.ComponentModel.DataAnnotations.Schema.Column(TypeName = "datetime2")]
        public DateTime CreatedAt_UtcDt { get; set; }
        [System.ComponentModel.DataAnnotations.Schema.Column(TypeName = "datetime2")]
        public DateTime CreatedAt_LocalDt { get; set; }

        public string LastUpdatedBy { get; set; }
        public string LastUpdatedBy_UserName { get; set; }
        [System.ComponentModel.DataAnnotations.Schema.Column(TypeName = "datetime2")]
        public DateTime LastUpdatedAt_UtcDt { get; set; }
        [System.ComponentModel.DataAnnotations.Schema.Column(TypeName = "datetime2")]
        public DateTime LastUpdatedAt_LocalDt { get; set; }

        public virtual ICollection<Tag> Tag { get; set; }
        public virtual ICollection<BlogIUDSqlHistory> BlogIUDSqlHistory { get; set; }
        public ICollection<Post> Post { get; set; }
        /*
        public List<Tag> Tag { get; set; }
        public List<Post> Post { get; set; }
        */
    }
}

The Tag model Tag.cs is the following:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;

namespace urlapp12.Models
{
    public class Tag
    {
        [Key]
        public int TagId { get; set; }
        public int DispOrderNbr { get; set; }
        public string tagItem { get; set; }
        public int Urlid { get; set; }

        public string CreatedBy { get; set; }
        public string CreatedBy_UserName { get; set; }
        [System.ComponentModel.DataAnnotations.Schema.Column(TypeName = "datetime2")]
        public DateTime CreatedAt_UtcDt { get; set; }
        [System.ComponentModel.DataAnnotations.Schema.Column(TypeName = "datetime2")]
        public DateTime CreatedAt_LocalDt { get; set; }

        public string LastUpdatedBy { get; set; }
        public string LastUpdatedBy_UserName { get; set; }
        [System.ComponentModel.DataAnnotations.Schema.Column(TypeName = "datetime2")]
        public DateTime LastUpdatedAt_UtcDt { get; set; }
        [System.ComponentModel.DataAnnotations.Schema.Column(TypeName = "datetime2")]
        public DateTime LastUpdatedAt_LocalDt { get; set; }

        [System.ComponentModel.DataAnnotations.Schema.ForeignKey("Urlid")]
        public Url Blog { get; set; }
    }
}

(2018-05-19 18:17 add) I have tried Mohsin Mehmood code, and unfortunately other errors occured.

Error CS0266 Cannot cast implicitly Type 'System.Linq.IQueryable' into 'Microsoft.EntityFrameworkCore.DbSet'. There is an explicit cast. (Are you missing cast?) C:\Users\mjkpt\source\repos\teststage\urlapp12\urlapp12\Controllers\TagsController.cs 45 Active

Error CS0266 Cannot cast implicitly Type 'Microsoft.EntityFrameworkCore.Query.IIncludableQueryable' into 'Microsoft.EntityFrameworkCore.DbSet'. There is an explicit cast. (Are you missing cast?) C:\Users\mjkpt\source\repos\teststage\urlapp12\urlapp12\Controllers\TagsController.cs 45 Active

(2018-05-19 18:43 Added)

It worked! Thank you very much user1672994
:It was necessary to make a little change like the following, but it is not a big problem:

(before change (user1672994's idea))

var blogging02Context = _context.Tag.Include(t => t.Blog).Where(t => t.Urlid == Urlid));

(after change)

var blogging02Context = _context.Tag.Include(t => t.Blog).Where(t => t.Urlid == Urlid);
like image 595
Kou Avatar asked May 19 '18 08:05

Kou


3 Answers

I ran into the same issue. Include produces a new abstraction level on top of IQueryable, called IIncludableQueryable. Your var blogging02Context becomes IIncludeQueryable which is not directly assignable from your Where statement.

Declare your blogging02Context variable as IQueryable<Tag> instead of var. It helped in my case.

        IQueryable<Tag> blogging02Context = _context.Tag.Include(t => t.Blog);

        if (!string.IsNullOrEmpty(Urlid.ToString()))
        {
            blogging02Context = blogging02Context.Where(t => t.Urlid == Urlid);
        }
like image 89
thomasgalliker Avatar answered Nov 02 '22 23:11

thomasgalliker


A couple things could be improved here.

First the answer to the topic question:

None of the previous answers seem to address the fact that while you can't implicitly convert IQueryable into IIncludableQueryable you can do the opposite. Additionally, IIncludableQueryable is only necessary if you intend to follow it with a ThenInclude() to include another entity based on the first included entity. [for example: context.Orders.Include(x => x.Customer).ThenInclude(x => x.BillingAddress)]

With that said, you could rewrite your code as follows:

// when using var
var blogging02Context = _context.Tag.Include(t => t.Blog).AsQueryable();

if (!string.IsNullOrEmpty(Urlid.ToString()))
{
   blogging02Context = blogging02Context.Where(t => t.Urlid == Urlid);
}

or

// or explicitly types
IQueryable<Tag> blogging02Context = _context.Tag.Include(t => t.Blog);

if (!string.IsNullOrEmpty(Urlid.ToString()))
{
   blogging02Context = blogging02Context.Where(t => t.Urlid == Urlid);
}

Which brings me to another issue with the original code... Why does your method take an integer as a parameter for Urlid only to then convert it to a string to check if it is a null or empty string?(see offending code below)

if (!string.IsNullOrEmpty(Urlid.ToString()))
{
   blogging02Context = blogging02Context.Where(t => t.Urlid == Urlid);
}

Is it possible for your method to be called without providing a value for Urlid? If so, then your Urlid will automatically be initialized to 0 (zero) which means your string validation will always produce the same result (it is never null or empty). Instead, you could make your Urlid parameter a nullable int like this:

Index(int id, Url blog, int? Urlid)

and just do a simple null check or a HasValue check

if (Urlid != null)
{
    blogging02Context = blogging02Context.Where(t => t.Urlid == Urlid);
}

or

if (Urlid.HasValue)
{
   blogging02Context = blogging02Context.Where(t => t.Urlid == Urlid);
}

or just check if it is greater than zero assuming your database doesn't allow for a Urlid of less than 1 (starts at 1)

if (Urlid > 0)
{
   blogging02Context = blogging02Context.Where(t => t.Urlid == Urlid);
}
like image 44
user17371590 Avatar answered Nov 02 '22 23:11

user17371590


The compile time error is correct as at the first line you have defined the var blogging02Context to _context.Tag.Include(....; This Include method returns Microsoft.EntityFrameworkCore.Query.IIncludableQueryable type. Later, you are adding where clause on the blogging02Context which returns System.Linq.IQueryable.

You can update the code with follows:

However, Another point Urlid is defined as int so this statement if (!string.IsNullOrEmpty(Urlid.ToString())) will never be false; as default value of int would be 0. and 0.ToString() will be "0".

    public async Task<IActionResult> Index(int id, 
    [Bind("Urlid,Userid,UrlStr,Title")] Url blog, int Urlid)
    {
        var blogging02Context = _context.Tag.Include(t => t.Blog).Where(t => t.Urlid == Urlid));

        ViewBag.Urlid = Urlid;
        return View(await blogging02Context.ToListAsync());
    }
like image 36
user1672994 Avatar answered Nov 03 '22 00:11

user1672994