Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Property 'Street' is not defined for type 'System.String' then sorting #6478

Closed
dvdobrovolskiy opened this issue Sep 6, 2016 · 12 comments
Closed
Assignees
Labels
closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-bug
Milestone

Comments

@dvdobrovolskiy
Copy link

dvdobrovolskiy commented Sep 6, 2016

I have an issue then I try to sort by field from subquery

here is code

model.Contacts = await _context.Apartments.Select(s => new ContactsVM
            {
                ApartmentId = s.ApartmentId,
                **Address = _context.Blocks.SingleOrDefault(b => b.BlockId == s.BlockId).Street,**
                Number = s.Number,
                Floor = s.Floor,
                Entrance = s.Entrance,
                MainPhone = s.MainPhone,
                SecondaryPhone = s.SecondaryPhone,
                TertiaryPhone = s.TertiaryPhone,
                QuaternaryPhone = s.QuaternaryPhone,
                QuinaryPhone = s.QuinaryPhone,
                SenaryPhone = s.SenaryPhone,
                SeptenaryPhone = s.SeptenaryPhone,
                OctonaryPhone = s.OctonaryPhone,
                NonaryPhone = s.NonaryPhone,
                DenaryPhone = s.DenaryPhone
            })
            **.OrderBy(o => o.Address)**
            .Skip(offset)
            .Take(DefaultPageSize)
            .ToListAsync();

and I get
ArgumentException: Property 'System.String Street' is not defined for type 'System.String'

@mafshin
Copy link

mafshin commented Sep 6, 2016

@dvdobrovolskiy what's the definition of Block entity?

Can you post your entities definitions and configuration s here so that others can reproduce it?

@dvdobrovolskiy
Copy link
Author

dvdobrovolskiy commented Sep 6, 2016

Nothing criminal IMHO

    public partial class Apartment
    {
        public Apartment() : base()
        {

        }

        [Key]
        public int ApartmentId { get; set; }

        [Required(ErrorMessage = "Укажите номер квартиры")]
        [Display(Name = "Номер")]
        public string Number { get; set; }

        [Display(Name = "Этаж")]
        public string Floor { get; set; }

        [Display(Name = "Подъезд")]
        public string Entrance { get; set; }

        public int BlockId { get; set; }
        public Block Block { get; set; }

        [Display(Name = "Основной телефон")]
        public string MainPhone { get; set; }

        [Display(Name = "Дополнительный телефон")]
        public string SecondaryPhone { get; set; }

        [Display(Name = "Дополнительный телефон")]
        public string TertiaryPhone { get; set; }

        [Display(Name = "Дополнительный телефон")]
        public string QuaternaryPhone { get; set; }

        [Display(Name = "Дополнительный телефон")]
        public string QuinaryPhone { get; set; }

        [Display(Name = "Дополнительный телефон")]
        public string SenaryPhone { get; set; }

        [Display(Name = "Дополнительный телефон")]
        public string SeptenaryPhone { get; set; }

        [Display(Name = "Дополнительный телефон")]
        public string OctonaryPhone { get; set; }

        [Display(Name = "Дополнительный телефон")]
        public string NonaryPhone { get; set; }        

        [Display(Name = "Дополнительный телефон")]
        public string DenaryPhone { get; set; }

    }

public partial class Block
    {
        public Block() : base()
        {

        }

        [Key]
        [ScaffoldColumn(false)]
        public int BlockId { get; set; }

        [Display(Name = "Обслуживается")]
        public bool IsInService { get; set; }

        [Display(Name = "Регион")]
        public string Region { get; set; }

        [Display(Name = "Район")]
        public string Rayon { get; set; }

        [Display(Name = "Город")]
        public string Town { get; set; }

        [Display(Name = "Населенный пункт")]
        public string InhabitatLocation { get; set; }

        [Required(ErrorMessage = "Укажите улицу")]
        [Display(Name = "Улица")]
        public string Street { get; set; }

        [Required(ErrorMessage = "Укажите номер дома")]
        [Display(Name = "Номер дома")]
        public string HouseNumber { get; set; }

        [Display(Name = "Корпус")]
        public string Korpus { get; set; }

        [Display(Name = "Строение")]
        public string Stroenie { get; set; }

        [Display(Name = "Псевдоним")]
        public string Alias { get; set; }

        [Display(Name = "Этажность")]
        public int? Stages { get; set; }

        [Display(Name = "Подъездов")]
        public int? Entrances { get; set; }

        [Display(Name = "Площадь")]
        public double? Square { get; set; }

        [Display(Name = "Количество квартир")]
        public int? NumberOfApartments { get; set; }

        [Required(ErrorMessage = "Укажите дату начала обслуживания")]
        [Display(Name = "Начало обслуживание")]
        [DataType(DataType.Date)]
        public DateTime? StartService { get; set; }

        [Display(Name = "Окончание обслуживания")]
        [DataType(DataType.Date)]
        public DateTime? EndService { get; set; }



        [Display(Name = "Квартиры")]
        public List<Apartment> Apartments { get; set; }

        [Display(Name = "Обслуживающая компания")]
        public int CompanyId { get; set; }
        public Company Company { get; set; }

        [Display(Name = "Ответственный")]
        [Required(ErrorMessage = "Укажите ответственного")]
        public int UserId { get; set; }
        public User User { get; set; }

    }


public class ContactsVM
    {
        [Key]
        [ScaffoldColumn(false)]
        public int ApartmentId { get; set; }

        [Display(Name = "Номер")]
        public string Number { get; set; }

        [Display(Name = "Этаж")]
        public string Floor { get; set; }

        [Display(Name = "Подъезд")]
        public string Entrance { get; set; }

        [Display(Name = "Адрес")]
        public string Address { get; set; }

        [Display(Name = "Основной телефон")]
        public string MainPhone { get; set; }

        [Display(Name = "Дополнительный телефон")]
        public string SecondaryPhone { get; set; }

        [Display(Name = "Дополнительный телефон")]
        public string TertiaryPhone { get; set; }

        [Display(Name = "Дополнительный телефон")]
        public string QuaternaryPhone { get; set; }

        [Display(Name = "Дополнительный телефон")]
        public string QuinaryPhone { get; set; }

        [Display(Name = "Дополнительный телефон")]
        public string SenaryPhone { get; set; }

        [Display(Name = "Дополнительный телефон")]
        public string SeptenaryPhone { get; set; }

        [Display(Name = "Дополнительный телефон")]
        public string OctonaryPhone { get; set; }

        [Display(Name = "Дополнительный телефон")]
        public string NonaryPhone { get; set; }

        [Display(Name = "Дополнительный телефон")]
        public string DenaryPhone { get; set; }
    }

@dvdobrovolskiy
Copy link
Author

I made sample application to reproduce error
dobrovolskiy.com/testapp.zip

@mafshin
Copy link

mafshin commented Sep 7, 2016

You may use s.Block.Street to have the query compile successfully.

But there seems to be a problem with the generated query underline:

from Apartment s in value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[testapp.Models.Apartment]) 
orderby 
{   from Block b in value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[testapp.Models.Block]) 
    where ([b].BlockId == [s].BlockId) 
    select [b].Street => SingleOrDefault()
} asc 
select new ContactsVM() 
{
    ApartmentId = [s].ApartmentId, 
    Address = {
        from Block b in value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[testapp.Models.Block]) 
        where ([b].BlockId == [s].BlockId) 
        select [b].Street => SingleOrDefault()
    }.Street, 
    Number = [s].Number, 
    Floor = [s].Floor, 
    ....

The Street is specified on both the select subquery and on the result of the select. Probably EF folks in charge of SQLite have some opinions on this.

@dvdobrovolskiy
Copy link
Author

MS SQL provider have same issue

@dvdobrovolskiy
Copy link
Author

It is pretty annoying issue. I cannot order and query if it is a little complicated.

        model.Categories = await _context.Categories.Select(s => new Category
        {
            CategoryId = s.CategoryId,
            ParentCategory = _context.Categories.SingleOrDefault(d => d.CategoryId == s.CategoryId),
            ParentId = s.ParentId,
            Title = s.Title

        })
        .OrderBy(o => o.ParentCategory.Title).ThenBy(o => o.Title)
        .Skip(offset)
        .Take(DefaultPageSize)
        .ToListAsync();

gives me

ArgumentException: Argument types do not match

Works fine without orderby subquery

@divega divega added this to the 1.1.0 milestone Sep 7, 2016
@divega divega added the type-bug label Sep 7, 2016
@smitpatel smitpatel changed the title Property 'System.String ' is not defined for type 'System.String' then sorting Property 'Street' is not defined for type 'System.String' then sorting Sep 7, 2016
@smitpatel
Copy link
Contributor

smitpatel commented Sep 8, 2016

This is a bug in our SubQueryMemberPushDownExpressionVisitor of query optimizer. We convert member access in subquerymodel to selector. Though the same subquerymodel is shared between both projection and orderby. This gives member access of Street on a subquery which is already projecting out Street (of type string) hence above exception is thrown.

Failing query:

AssertQuery<Order, Customer>((os, cs) =>
        os.Select(o => new
        {
            OrderId = o.OrderID,
            City = cs.SingleOrDefault(c => c.CustomerID == o.CustomerID).City
        })
        .OrderBy(o => o.City));

@dvdobrovolskiy
Copy link
Author

hmm
any workaround till we wait for 1.1 in Q4 2016 / Q1 2017?

@smitpatel
Copy link
Contributor

@dvdobrovolskiy - You can call OrderBy after ToList call to apply ordering on client, which would avoid this problem.

@dvdobrovolskiy
Copy link
Author

No good to me as I use
.Skip(offset)
.Take(DefaultPageSize)

sorting list after this has no point.
Sadly I have to rollback to RC1 or back to good old ASP.Net 5

@ErikEJ
Copy link
Contributor

ErikEJ commented Sep 10, 2016

If you are on Windows, you can use EF6 with ASP.NET Core 😄

@dvdobrovolskiy
Copy link
Author

True. Didn`t think about that. tnks!

@smitpatel smitpatel added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Sep 19, 2016
@ajcvickers ajcvickers modified the milestones: 1.1.0-preview1, 1.1.0 Oct 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-bug
Projects
None yet
Development

No branches or pull requests

6 participants