简体   繁体   中英

Part of LINQ query to seperate method (EF Core)

I guess this has been asked before but i don't find any good examples. I have this query.

series = await query
    .GroupBy(o => new { o.AddedDate.Date.Month, o.AddedDate.Date.Year })
    .Select(g => new DateLineGraphItem 
        { Legend = new DateTime(g.Key.Year, g.Key.Month, 1), Number = g.Count() })
    .ToListAsync();

Everything is the same all the time except that my DB has different names for all the "AddedDate" column and i'm trying to figure out how i can break this out into it's own method, something like this.

List<DateLineGraphItem> series = GroupByAndSelect("AddedDate")
List<DateLineGraphItem> series = GroupByAndSelect("CreatedDate")

Do i have to use Expressions and Predicates and all that or it is possible to do in some simple manner?

Do i have to use Expressions

It's always better to use expressions (the whole LINQ is based on that concept) than magic strings. The only problem is that there is no out of the box solution for composing expressions from other expressions, so you need to write your own or use 3rd party packages.

From the other side, the nameof operator eliminates most of the string drawbacks. And EF Core provides a handy method called EF.Property for simple scenarios like this.

So if the method contains string propertyName argument which points to direct property of type DateTime , you can simply replace the o.AddedDate with EF.Property<DateTime>(o, propertyName) , eg

series = await query
    .GroupBy(o => new { EF.Property<DateTime>(o, propertyName).Date.Month, EF.Property<DateTime>(o, propertyName).Date.Year })
    .Select(g => new DateLineGraphItem 
        { Legend = new DateTime(g.Key.Year, g.Key.Month, 1), Number = g.Count() })
    .ToListAsync();

I had the same problem. You may extend your entity class using an interface which contains a DateTime Field, like this:

    public class EntityDb1 : IDatedEntity
    {
        public DateTime AddedDate { get; set; }

        public DateTime MyDate => AddedDate;
    }
    public class EntityDb2 : IDatedEntity
    {
        public DateTime CreatedDate { get; set; }

        public DateTime MyDate => CreatedDate;
    }

    public interface IDatedEntity
    {
        DateTime MyDate{ get; }
    }

Then execute the query

        public class Test
        {
            public static async Task<IEnumerable<DateLineGraphItem>> ExecuteQuery(IQueryable<IDatedEntity> entityList)
            {
                return await entityList
                    .GroupBy(o =>new { o.MyDate.Date.Month, o.MyDate.Date.Year })
                    .Select(g => new DateLineGraphItem(){ Legend = new DateTime(g.Key.Year, g.Key.Month, 1), Number = g.Count() })
                    .ToListAsync();
            }
        }

        public class DateLineGraphItem
        {
            public DateTime Legend { get; set; }
            public int Number { get; set; }
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM