I'm trying to get the number of tasks performed on a daily basis and plot them into a chart, but the thing is I can't figure out the pomelo entity code.
Select FirstName,count(ToDoId)
From todos as M
Inner join users as u
on M.UserId=u.UserId
where u.UserId=1
GROUP BY M.UserId, CAST(M.CreatedAt AS DATE)
Assuming corresponding model classes for your two tables, that contain navigation properties, the LINQ query could look like this:
var todoCountByFirstNameAndDate = context.Todos.Include(e => e.User)
.GroupBy(t => new {t.User.FirstName, t.CreatedAt.Date})
.Select(g => new {g.Key.FirstName, g.Key.Date, TodoCount = g.Count()})
.ToList();
The generated SQL would then be:
SELECT `u`.`FirstName`, CONVERT(`t`.`CreatedAt`, date) AS `Date`, COUNT(*) AS `TodoCount`
FROM `Todos` AS `t`
INNER JOIN `Users` AS `u` ON `t`.`UserId` = `u`.`UserId`
GROUP BY `u`.`FirstName`, CONVERT(`t`.`CreatedAt`, date)
Here is a complete and working console sample project, that demonstrates the bits and pieces:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Pomelo.EntityFrameworkCore.MySql.Infrastructure;
namespace IssueConsoleTemplate
{
//
// Entities:
//
public class User
{
public int UserId { get; set; }
public string FirstName { get; set; }
public virtual ICollection<Todo> Todos { get; set; } = new HashSet<Todo>();
}
public class Todo
{
public int TodoId { get; set; }
public DateTime CreatedAt { get; set; }
public int UserId { get; set; }
public User User { get; set; }
}
//
// DbContext:
//
public class Context : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Todo> Todos { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.UseMySql(
"server=127.0.0.1;port=3306;user=root;password=;database=So67149928",
b => b.ServerVersion("8.0.21-mysql")
.CharSetBehavior(CharSetBehavior.NeverAppend))
.UseLoggerFactory(
LoggerFactory.Create(
b => b
.AddConsole()
.AddFilter(level => level >= LogLevel.Information)))
.EnableSensitiveDataLogging()
.EnableDetailedErrors();
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<User>()
.HasData(
new User {UserId = 1, FirstName = "John"},
new User {UserId = 2, FirstName = "Jane"});
modelBuilder.Entity<Todo>()
.HasData(
new Todo {TodoId = 11, CreatedAt = new DateTime(2021, 4, 17, 14, 21, 41), UserId = 1},
new Todo {TodoId = 12, CreatedAt = new DateTime(2021, 4, 17, 18, 11, 21), UserId = 1},
new Todo {TodoId = 13, CreatedAt = new DateTime(2021, 4, 17, 14, 21, 41), UserId = 2},
new Todo {TodoId = 14, CreatedAt = new DateTime(2021, 4, 18, 18, 11, 21), UserId = 2});
}
}
internal static class Program
{
private static void Main()
{
using var context = new Context();
context.Database.EnsureDeleted();
context.Database.EnsureCreated();
var todoCountByFirstNameAndDate = context.Todos.Include(e => e.User)
.GroupBy(t => new {t.User.FirstName, t.CreatedAt.Date})
.Select(g => new {g.Key.FirstName, g.Key.Date, TodoCount = g.Count()})
.OrderBy(r => r.FirstName)
.ThenBy(r => r.Date)
.ToList();
Trace.Assert(todoCountByFirstNameAndDate.Count == 3);
Trace.Assert(todoCountByFirstNameAndDate[0].FirstName == "Jane");
Trace.Assert(todoCountByFirstNameAndDate[0].Date == new DateTime(2021, 4, 17));
Trace.Assert(todoCountByFirstNameAndDate[0].TodoCount == 1);
Trace.Assert(todoCountByFirstNameAndDate[1].FirstName == "Jane");
Trace.Assert(todoCountByFirstNameAndDate[1].Date == new DateTime(2021, 4, 18));
Trace.Assert(todoCountByFirstNameAndDate[1].TodoCount == 1);
Trace.Assert(todoCountByFirstNameAndDate[2].FirstName == "John");
Trace.Assert(todoCountByFirstNameAndDate[2].Date == new DateTime(2021, 4, 17));
Trace.Assert(todoCountByFirstNameAndDate[2].TodoCount == 2);
}
}
}
Related
Since moving on from .net to .Net Core, Ive had to look for a WebGrid Replacement, which lead me to NonFactors MVC6 grid. I have gotten all the basic understanding of how all if works, now I am trying to understand how to use "#helper" function to display reusable HTML in the table.
Previously in .Net #helper allowed for defining customer HTML then using it in WebGrid, like so The Helper Function and the webgrid Webgrid. Now im currently learning how to do the same functionality in Razor Pages, and im currently at a dead end.
What I would Like to do, is using the MVC6 grid (Grid) with this custom checkbox (HTML)
When using the MVC6 Grid to add column, you could use the RenderedAs() and Html.Raw() method to add the checkbox. Code like this:
Model:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public string MaritalStatus { get; set; }
public int Age { get; set; }
public DateTime Birthday { get; set; }
public bool IsWorking { get; set; }
public bool IsSelected { get; set; }
}
public class PersonViewModel
{
public List<Person> Persons { get; set; }
public List<string> SelectedName { get; set; }
}
Controller:
public IActionResult Index3()
{
//Initial data.
var personvm = new PersonViewModel()
{
Persons = new List<Person>()
{
new Person() { Id = 1, Name = "Joe", Surname = "Crosswave", MaritalStatus = "Married", Age = 32, Birthday = DateTime.Now, IsWorking = false },
new Person() { Id = 2, Name = "Merry", Surname = "Lisel", MaritalStatus = "Widowed", Age = 42, Birthday = DateTime.Now, IsWorking = false },
new Person() { Id = 3, Name = "Henry", Surname = "Crux", MaritalStatus = "Single", Age = 29, Birthday = DateTime.Now, IsWorking = true },
new Person() { Id = 4, Name = "Cody", Surname = "Jurut", MaritalStatus = "", Age = 49, Birthday = DateTime.Now, IsWorking = false },
new Person() { Id = 5, Name = "Simon", Surname = "Scranton", MaritalStatus = "Single", Age = 34, Birthday = DateTime.Now, IsWorking = false },
new Person() { Id = 6, Name = "Leena", Surname = "Laurent", MaritalStatus = "Divorced", Age = 19, Birthday = DateTime.Now, IsWorking = false },
new Person() { Id = 7, Name = "Ode", Surname = "Cosmides", MaritalStatus = "Married", Age = 54, Birthday = DateTime.Now, IsWorking = true },
new Person() { Id = 8, Name = "Nicky", Surname = "Cassel", MaritalStatus = "Married", Age = 32, Birthday = DateTime.Now, IsWorking = true }
},
SelectedName = new List<string>() { "Merry", "Henry", "Leena", "Nicky" }
};
return View(personvm);
}
View: check the last column.
#model PersonViewModel
#(Html
.Grid(Model.Persons)
.Build(columns =>
{
columns.Add(model => Html.CheckBox("Check_" + model.Id)).Titled(Html.CheckBox("CheckAll"));
columns.Add().RenderedAs((model, row) => row + 1).Titled("#").Css("text-center");
columns.Add(model => model.Name).Titled("Name");
columns.Add(model => model.Surname).Titled("Surname");
columns.Add(model => model.MaritalStatus).Titled("Marital status");
columns.Add(model => model.Age).Titled("Age");
columns.Add(model => model.Birthday).Titled("Birthday").Formatted("{0:d}");
columns.Add(model => model.IsWorking).Titled("Employed").RenderedAs(model => model.IsWorking == true ? "Employed" : "Unemployed");
columns.Add(model => model.IsSelected).Titled("Selected")
.RenderedAs(model => Model.SelectedName.Contains(model.Name) ?
Html.Raw("<input type='checkbox' name='Input.SelectedAccessRightsIds' value='"+ model.Id + "' checked />")
: Html.Raw("<input type='checkbox' name='Input.SelectedAccessRightsIds' value='" + model.Id + "' />"));
})
)
The output as below:
Reference: MVC6 Grid Formatting
[Note] Before using MVC6 Grid, please make sure you have installed it.
I wrote a method to show Items and in Groups in DropDownlist with SelectListItem, But the problem is that only show the first group name and child plus the childs of other groups. The problem is that do not show second, third,.. groups (but show their childs).
My model is
public class PermissionsViewModel
{
public long ID { get; set; }
public string Title { get; set; }
public long TypeId { get; set; }
public long? ParentId { get; set; }
public string ParentTitle { get; set; }
public List<PermissionsViewModel> ParentList { get; set; }
public List<PermissionsViewModel> OperationsList { get; set; }
public List<PermissionTypesDto> PermissionTypesList { get; set; }
public bool Status { get; set; }
}
Method to retrieve data:
public Dictionary<long?,List<PermissionsViewModel>> GetPermissionsByModule()
{
var ItemValue = (_ipermissionTypes.Expose().FirstOrDefault(x => x.Title == "Operation").Id);
var permissionbymodule = _ntumcontext.Tbl_Permissions
.Where(x => x.Status == true && x.TypeId == ItemValue)
.Select(x => new PermissionsViewModel
{
ID = x.ID,
Title = x.Title,
Status = x.Status,
ParentId = x.ParentId,
ParentTitle=x.permission.Title,
TypeId=x.TypeId,
}).AsEnumerable().GroupBy(x => x.ParentId).ToList();
return permissionbymodule.ToDictionary(k => k.Key, v => v.ToList());
}
And the Method to get on razor page (View):
public List<SelectListItem> Permissions = new List<SelectListItem>();
public List<SelectListItem> GetPermissionsByModule()
{
var AllPermissions = _ipermissionsApplication.GetPermissionsByModule();
foreach (var (key, value) in AllPermissions)
{
var parentTitle = _ipermissionsApplication.GetDetails(key).Title; //get group title from key
var group = new SelectListGroup() { Name = parentTitle };
foreach (var per in value)
{
var item = new SelectListItem(per.Title, per.ID.ToString())
{
Group = group
};
Permissions.Add(item);
}
}
return Permissions;
}
And in cshtml :
<select asp-for="RoleVM.SelectedPermissions" asp-items="Model.Permissions">
At present with the above codes, the problem is that do not show the second and third and ... , only show the first group name, but show all child items of all groups.
Firstly,you need to check the value of AllPermissions,maybe the parentID is not exists,and then you need to check var parentTitle = _ipermissionsApplication.GetDetails(key).Title;maybe the second and third and.. parentTitle is null.
Here is a working demo(I use fake data):
public class TestPermissionsModel : PageModel
{
public List<SelectListItem> Permissions = new List<SelectListItem>();
public void GetPermissionsByModule()
{
var AllPermissions = new Dictionary<long, List<PermissionsViewModel>>()
{
{1,new List<PermissionsViewModel>{ new PermissionsViewModel{ ID=11,Title="title11", ParentId=1}, new PermissionsViewModel { ID = 12, Title = "title12", ParentId = 1 } } },
{2,new List<PermissionsViewModel>{ new PermissionsViewModel{ ID=21,Title="title21", ParentId=2}, new PermissionsViewModel { ID = 22, Title = "title22", ParentId = 2 } } },
{3,new List<PermissionsViewModel>{ new PermissionsViewModel{ ID=31,Title="title31", ParentId=3}, new PermissionsViewModel { ID = 32, Title = "title32", ParentId = 3 } } }
};
foreach (var (key, value) in AllPermissions)
{
var parentTitle = "parentTitle" + key; //get group title from key
var group = new SelectListGroup() { Name = parentTitle };
foreach (var per in value)
{
var item = new SelectListItem(per.Title, per.ID.ToString())
{
Group = group
};
Permissions.Add(item);
}
}
}
public void OnGet()
{
GetPermissionsByModule();
}
}
View:
<select asp-items="Model.Permissions"></select>
result:
I would like to seed my Database with EF Core and seeding the connecting table for the many-to-many relationship doesn't work.
I've got three models:
public class Droid
{
public int DroidId { get; set; }
public string DroidName { get; set; }
}
public class Colors
{
public int ColorID { get; set; }
public string Color { get; set; }
}
public class DroidColors
{
public int DroidColorID { get; set; }
public int ColorID { get; set; }
public int DroidID { get; set; }
}
And I'm seeding the database right at the beginning. Seeding the droid table and the color table works fine, but the droidcolor table just stays emtpy.
using (var context = new DBContext(serviceProvider.GetRequiredService<DbContextOptions<DBContext>>()))
{
if (context.Colors.Any())
{
return;
}
var colors = new Color[]
{
new Color{Color = "White"},
new Parameter{Color = "Black" },
new Parameter{Color = "Orange"},
};
foreach (Color c in colors)
{
context.Colors.Add(c);
}
context.SaveChanges();
if (context.Droids.Any())
{
return;
}
var droids = new Droid[]
{
new Droid{DroidName = "R2-D2"},
new Droid{DroidName = "C-3PO"},
new Droid{DroidName = "BB-8"},
};
foreach (Droid d in droids)
{
context.Droids.Add(d);
}
context.SaveChanges();
if (context.DroidColors.Any())
{
return;
}
var droidcolors = new DroidColor[]
{
new DroidColor{DroidID = 1, ColorID = 1},
new DroidColor{DroidID = 1, ColorID = 2},
new DroidColor{DroidID = 2, ColorID = 1},
new DroidColor{DroidID = 2, ColorID = 2},
new DroidColor{DroidID = 2, ColorID = 3},
new DroidColor{DroidID = 3, ColorID = 1},
new DroidColor{DroidID = 3, ColorID = 3}
};
foreach (DroidColor DC in droidcolors)
{
context.Droids.Add(DC);
}
context.SaveChanges();
What am I missing? EF Core seems to ignore my third data array, after working with the first and the second as expected.
I am trying to set up a Design Time Data binding in a Xamarin XAML page so I can utilise the previewer to design my page more quickly. I have set up a static class which contains my data, but when I preview it does not show me the bound data.
How do I get the binding to work? I am trying it with the Test property
XAML
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:TechsportiseApp.Data;assembly=DesignTimeData"
BindingContext="{x:Static local:DesignTimeData.ViewModel}"
x:Class="TechsportiseApp.Views.Timer" x:Name="ParentView" Title="Timer">
<Entry Margin = "3" Text="{Binding Test}" />
</ContentPage>
DesignTimeData.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using TechsportiseApp.Models;
namespace TechsportiseApp.Data
{
public class DesignTimeData
{
public static class ViewModelLocator
{
private static TimerViewModel timerVM;
public static TimerViewModel ViewModel => timerVM ?? (timerVM = new TimerViewModel());
public class TimerViewModel
{
public ObservableCollection<Timing> Timings { get; set; } = new ObservableCollection<Timing>
{
new Timing { Position = 1, BatchCode = "A", Elapsed = "01:02:03.001", EndTime = DateTime.Now, StartTime = DateTime.Now, Id = 1, RaceId = 111 }
};
public List<RaceOption> RaceOptions { get; set; } = new List<RaceOption>
{
new RaceOption { Id = 1, RaceId = 2, Colour= "Red", OptionName="5k" },
new RaceOption { Id = 3, RaceId = 4, Colour= "Blue", OptionName="10k" },
new RaceOption { Id = 5, RaceId = 6, Colour= "Green", OptionName="15k" },
new RaceOption { Id = 5, RaceId = 8, Colour= "Yello", OptionName="20k" },
};
public string Test = "Bind Test";
}
}
}
}
public class TimerViewModel
{
private string _test = "Bind Test";
public string Test
{
get
{
return _test;
}
set
{
value = _test;
//implement your INotifyOnPropertyChangedHere...
}
}
/// the rest of your view model code
}
It looks like you have not properly defined your class. Change the below structure
From
namespace TechsportiseApp.Data
{
public class DesignTimeData
{
public static class ViewModelLocator
{
private static TimerViewModel timerVM;
public static TimerViewModel ViewModel => timerVM ?? (timerVM = new TimerViewModel());
public class TimerViewModel
{
public ObservableCollection<Timing> Timings { get; set; } = new ObservableCollection<Timing>
{
new Timing { Position = 1, BatchCode = "A", Elapsed = "01:02:03.001", EndTime = DateTime.Now, StartTime = DateTime.Now, Id = 1, RaceId = 111 }
};
public List<RaceOption> RaceOptions { get; set; } = new List<RaceOption>
{
new RaceOption { Id = 1, RaceId = 2, Colour= "Red", OptionName="5k" },
new RaceOption { Id = 3, RaceId = 4, Colour= "Blue", OptionName="10k" },
new RaceOption { Id = 5, RaceId = 6, Colour= "Green", OptionName="15k" },
new RaceOption { Id = 5, RaceId = 8, Colour= "Yello", OptionName="20k" },
};
public string Test = "Bind Test";
}
}
}
}
To
namespace TechsportiseApp.Data
{
public class DesignTimeData
{
private static TimerViewModel timerVM;
public static TimerViewModel ViewModel => timerVM ?? (timerVM = new TimerViewModel());
public class TimerViewModel
{
public ObservableCollection<Timing> Timings { get; set; } = new ObservableCollection<Timing>
{
new Timing { Position = 1, BatchCode = "A", Elapsed = "01:02:03.001", EndTime = DateTime.Now, StartTime = DateTime.Now, Id = 1, RaceId = 111 }
};
public List<RaceOption> RaceOptions { get; set; } = new List<RaceOption>
{
new RaceOption { Id = 1, RaceId = 2, Colour= "Red", OptionName="5k" },
new RaceOption { Id = 3, RaceId = 4, Colour= "Blue", OptionName="10k" },
new RaceOption { Id = 5, RaceId = 6, Colour= "Green", OptionName="15k" },
new RaceOption { Id = 5, RaceId = 8, Colour= "Yello", OptionName="20k" },
};
public string Test = "Bind Test";
}
}
}
This should resolve your issue
I'm attempting to apply Ayende's order search from here to an existing index.
The current index looks like this:
public class HomeBlurb_IncludeTotalCosts_Search2 : AbstractIndexCreationTask<MPDocument, HomeBlurb_IncludeTotalCosts_Search2.ReduceResult>
{
public class ReduceResult
{
public string Name { get; set; }
public string Constituency { get; set; }
public decimal? AmountPaid { get; set; }
}
public HomeBlurb_IncludeTotalCosts_Search2()
{
Map = mps => from mp in mps
from exp in mp.Expenses
select new
{
mp.Name,
mp.Constituency,
exp.AmountPaid
};
Reduce = results => from result in results
group result by new { result.Name, result.Constituency } into g
select new
{
Name = g.Key.Name,
Constituency = g.Key.Constituency,
AmountPaid = g.Sum(x => x.AmountPaid)
};
Index(x => x.Name, FieldIndexing.Analyzed);
Index(x => x.Constituency, FieldIndexing.Analyzed);
}
}
This index works fine. However when I try to change the Map to:
from mp in mps
from exp in mp.Expenses
select new
{
Query = new object[]{mp.Name,mp.Constituency},
mp.Name,
mp.Constituency,
exp.AmountPaid
};
and the reduce to
from result in results
group result by new { result.Name, result.Constituency } into g
select new
{
Query = "",
Name = g.Key.Name,
Constituency = g.Key.Constituency,
AmountPaid = g.Sum(x => x.AmountPaid)
};
I then get no results when querying on the Query property. If I remove the reduce the index returns data, but it always returns the full MPDocument, which is much more that I was to materialise. Is there a way to use the technique described in the original post that also utilises a reduce?
You can use this in your reduce function:
Query = g.Select(x => x.Query).Where(x => x != null).FirstOrDefault()
In order to query on that field, you need to have a seperate query model and a result model. Here is a full example using your code:
public class MultiTermFieldInMapReduce
{
public class MPDocument
{
public List<Epense> Expenses { get; set; }
public string Name { get; set; }
public string Constituency { get; set; }
public class Epense
{
public decimal? AmountPaid { get; set; }
}
}
public class HomeBlurb_IncludeTotalCosts_Search2 : AbstractIndexCreationTask<MPDocument, HomeBlurb_IncludeTotalCosts_Search2.ReduceResult>
{
public class ReduceResult
{
public string Name { get; set; }
public string Constituency { get; set; }
public decimal? AmountPaid { get; set; }
public object[] Query { get; set; }
}
public class SearchModel
{
public string Name { get; set; }
public string Constituency { get; set; }
public decimal? AmountPaid { get; set; }
public string Query { get; set; }
}
public HomeBlurb_IncludeTotalCosts_Search2()
{
Map = mps => from mp in mps
from exp in mp.Expenses
select new
{
mp.Name,
mp.Constituency,
exp.AmountPaid,
Query = new object[]
{
mp.Name,
mp.Constituency
}
};
Reduce = results => from result in results
group result by new { result.Name, result.Constituency } into g
select new
{
Name = g.Key.Name,
Constituency = g.Key.Constituency,
AmountPaid = g.Sum(x => x.AmountPaid),
Query = g.Select(x => x.Query).Where(x => x != null).FirstOrDefault()
};
Index(x => x.Name, FieldIndexing.Analyzed);
Index(x => x.Constituency, FieldIndexing.Analyzed);
}
}
[Fact]
public void Query_returns_results()
{
using (var store = new EmbeddableDocumentStore { RunInMemory = true }.Initialize())
{
using (var session = store.OpenSession())
{
session.Store(new MapReduceError.MPDocument
{
Name = "test1",
Expenses = new List<MapReduceError.MPDocument.Epense>
{
new MapReduceError.MPDocument.Epense {AmountPaid = 5.5m},
new MapReduceError.MPDocument.Epense {AmountPaid = 5.5m},
new MapReduceError.MPDocument.Epense {AmountPaid = 5.5m},
new MapReduceError.MPDocument.Epense {AmountPaid = 5.5m}
}
});
session.Store(new MapReduceError.MPDocument
{
Name = "test2",
Expenses = new List<MapReduceError.MPDocument.Epense>
{
new MapReduceError.MPDocument.Epense {AmountPaid = 10},
new MapReduceError.MPDocument.Epense {AmountPaid = 10},
new MapReduceError.MPDocument.Epense {AmountPaid = 10},
new MapReduceError.MPDocument.Epense {AmountPaid = 10}
}
});
session.SaveChanges();
}
new HomeBlurb_IncludeTotalCosts_Search2().Execute(store);
using (var session = store.OpenSession())
{
var results =
session.Query
<HomeBlurb_IncludeTotalCosts_Search2.SearchModel, HomeBlurb_IncludeTotalCosts_Search2>()
.Customize(x => x.WaitForNonStaleResultsAsOfLastWrite())
.Where(x => x.Query == "test1")
.As<HomeBlurb_IncludeTotalCosts_Search2.ReduceResult>()
.ToList();
Assert.Equal(1, results.Count);
Assert.Equal(22, results.First().AmountPaid);
}
}
}
}
I don't think you need a Map/Reduce index to do this, you seem to only be reducing on MPDocument Name and Constituency, which I guess are unique to each MP.
I think that you want to use TransformResults, so that you can change the shape of the output instead, something like so:
TransformResults =
(database, mps) => from mp in mps
select new
{
mp.Name,
mp.???
< JUST THE BITS YOU WANT RETURNED >
};
Then you query like so:
session.Query<mp>("index name")
.Where(..)
.As<MPQueryResult>()
.ToList()