0

I'm sorry for the question form, as I don't know what is the name of this concept. If there are any suggestions I'll change it.

I View Model VMHome and I need to make one of its props to be like this

List<string,string,int> 

Because I have Iqueryable result and I think that structure would be corresponding. Anyway here is the needed cast message

It is basically Iqueryable like this when using var

enter image description here

after my attempt, it looks like this when using view model

enter image description here

and here is my attempt to make "immutable struct"

public class VMHome
{
    
    public List<categoryListPostCount> CategoryListPostCount { get; set; }

    // immutable struct
    public struct categoryListPostCount
    {
        public categoryListPostCount(string categoryName, string categoryID, int count)
        {
            CategoryName = categoryName;
            CategoryID = categoryID;
            Count = count;
        }

        public string CategoryName { get; set; }
        public string CategoryID { get; set; }
        public int Count { get; set; }
    }

}

And here is the faulty usage

// ... inject vmHome.. and then 
vmHome.CategoryListPostCount = 
    (from cat in context.postCategories
    join con in context.postContents
    on cat.Id equals con.postCatId
    group new { cat, con } by new { con.postCatId, cat.categoryName } into g
    select new
    {
        //g.Key,
        CategoryName = g.Key.categoryName.ToString(),
        CategoryID = g.Key.postCatId.ToString(),
        Count = g.Count()
    }).ToList();
5
  • You're creating an anonymous object instead of an instance of your struct. Call your struct constructor instead of new { ... }. Commented Jul 25, 2021 at 8:40
  • 2
    Other's have already pointed out the error (constructing anonymous object instead of struct), but I have another suggestion: You can use record to declare your type more succinctly like so: public sealed record categoryListPostCount(string CategoryName, string CategoryID, int Count); Commented Jul 25, 2021 at 9:15
  • 1
    I agree with @MatthewWatson: using dot net 5 a record might be a better alternative than a value tuple or an anonymous type. Commented Jul 25, 2021 at 11:20
  • @ZoharPeled would you please show me an example how to use it? Commented Jul 26, 2021 at 13:32
  • there are plenty of examples on how to use records online.... Commented Jul 26, 2021 at 16:20

2 Answers 2

3

You are selecting the result of your query in an anonymous type. You should create type of your struct using new VMHome.categoryListPostCount.

vmHome.CategoryListPostCount = 
    (from cat in context.postCategories
    join con in context.postContents
    on cat.Id equals con.postCatId
    group new { cat, con } by new { con.postCatId, cat.categoryName } into g
    select new VMHome.categoryListPostCount
    {
        CategoryName = g.Key.categoryName.ToString(),
        CategoryID = g.Key.postCatId.ToString(),
        Count = g.Count()
    }).ToList();
Sign up to request clarification or add additional context in comments.

Comments

3

modern dot net supports value tuples (started in dot net framework 4.7) - which basically provides immutable structs out of the box for up to 8 properies.

So instead of a List<string,string,int> you can use List<(string,string,int)> - or even better - name your properties: List<(string CatgoryName,string CategoryId, int Count)>

Another option would be to use anonymous types which are supported since linq was introduced (meaning .Net 3 IIRC). The downside is that you can't declare a list of anonymous types the same way, you must use var.
Sometimes its more convenient, sometimes its less readable.

Also, the struct you've created is not immutable - being immutable means that its properties values can't be changed after it was created. In c# 9 or higher you can use {get;init;} for immutable properties, in c# 6 or higher you can use {get;} for immutable properties, and in earlier versions you can only achieve immutability by using explicit readonly backing fields to properties.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.