Hello I have problems Table for Reeves and I am trying to check which reeve creates most problem. So here is my Problem Model;
public int Id { get; set; }
public string Name { get; set; }
public string Text { get; set; }
public short Sira { get; set; }
public DateTime Created { get; set; }
public virtual Topic Topic { get; set; }
public virtual Member WhoIs { get; set; }
public virtual Province Province { get; set; }
public virtual Town Town { get; set; }
public virtual District District { get; set; }
public virtual Reeve Reeve { get; set; }
As you see I have Reeve as a virtual table.When I create table I get Reeve_Id and Trying to .GroupBy(m => m.Reeve.Id) So here is the code ;
public ActionResult GroupByReeve()
{
var model = new ProblemModel
{
ProblemsList = Db.Problems.GroupBy(m => m.Reeve.Id)
.Select(s => new ProblemModel.ProblemForView
{
Id = s.FirstOrDefault().Id,
CountItem = s.Count(),
AllItem = Db.Problems.Count(),
ReeveName=s.FirstOrDefault().Reeve.Name
})
};
return View(model);
}
So I can groupby problems by their Id not by ReeveId.The view returns 4 items(4 problems) But they are belong to only 2 Reeves So it must show 2 items not 4 items. How can I do it ?
I'm not sure, why your code doesn't work (it looks like it should), but here is how you use GroupBy properly:
ProblemsList = Db.Problems.GroupBy(m => m.Reeve.Id,
s => new ProblemModel.ProblemForView
{
Id = s.FirstOrDefault().Id,
CountItem = s.Count(),
AllItem = Db.Problems.Count(),
ReeveName=s.FirstOrDefault().Reeve.Name
});
Related
I want to retrieve all players from db for one club where they are in M:M relationship using PlayerClubs join table. My code is working but really doesn't want that approach for example, first I am retrieving all players from db
var players = await _context.PlayerClubs.Where(pc => pc.ClubId == id).Select(p => p.Player).ToListAsync();
then I retrieve the club based on id which I receive from controller
var club = await _context.Clubs.Where(z => z.Id == id).FirstOrDefaultAsync();
and lastly populate ClubViewModel with this data
return new ClubViewModel()
{
Players = players,
Club = club,
};
Now I want to populate this new ClubViewModel with just one db call i.e. one query using linq expression.
Things that I have tried
var query = (from c in _context.Clubs
join pc in _context.PlayerClubs on c.Id equals pc.ClubId
join player in _context.Players on pc.PlayerId equals player.Id
where c.Id == id
select new ClubViewModel
{
Players = player,
Club = c,
}).ToListAsync();
but I got stuck.
PlayerClubs table
Club
public class Club
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[EnumDataType(typeof(Gender))]
public Gender GenderType { get; set; }
public int SeasonId { get; set; }
public virtual Season Season { get; set; }
[Required]
public string YearOfEstablishment { get; set; }
[Required]
public string YearOfEntryIntoLeague { get; set; }
public string Note { get; set; }
[ForeignKey("League")]
public int LeagueId { get; set; }
public virtual League League { get; set; }
public virtual ICollection<PlayerClub> PlayerClubs { get; set; }
public virtual ICollection<CoachClub> CoachClubs { get; set; }
}
Player
public class Player
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
public string FullName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}")]
public DateTime Birth { get; set; }
public int LicenseNumber { get; set; }
public string Note { get; set; }
public virtual List<string> Clubs { get; set; }
public virtual List<Club> Klubovi { get; set; }
public virtual List<string> ClubNames { get; set; }
[StringLength(13, ErrorMessage = "Матичниот број не може да биде подолг од 13 цифри")]
public string Embg { get; set; }
public virtual ICollection<PlayerClub> PlayerClubs { get; set; }
public Player()
{
Clubs = new List<string>();
ClubNames = new List<string>();
Klubovi = new List<Club>();
}
}
PlayerClub
public class PlayerClub
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[ForeignKey("Club")]
public int ClubId { get; set; }
[ForeignKey("Player")]
public int PlayerId { get; set; }
public virtual Club Club { get; set; }
public virtual Player Player { get; set; }
}
ClubViewModel
public class ClubViewModel : Club
{
public Club Club { get; set; }
public List<Player> Players { get; set; }
public ClubViewModel()
{
Players = new List<Player>();
}
}
Your query:
var query =
from c in _context.Clubs
where c.Id == id
select new ClubViewModel
{
Players = c.PlayerClubs.Select(pc => pc.Player).ToList(),
Club = c,
};
var result = await query.ToListAsync();
I'm trying to join three tables in a view model. It works with two tables but crashes when I add a third. Here are the models and the controller. The models section_detail, phone, and department were generated by Entity Framework.
EmployeeViewModel was created by copying properties from the other models. I've abbreviated some of the models shown here with:
public partial class section_detail
{
public int section_detail_id { get; set; }
public Nullable<int> parent_section_det_id { get; set; }
. . .
public string Comments { get; set; }
public string email { get; set; }
public virtual department department { get; set; }
public virtual phone phone { get; set; }
}
public partial class phone
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public phone()
{
this.section_detail = new HashSet<section_detail>();
}
public int phone_id { get; set; }
public string area_code { get; set; }
public string phone_nbr { get; set; }
. . .
public string activity_code { get; set; }
public string function_code { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<section_detail> section_detail { get; set; }
public virtual BudgetUnit BudgetUnit { get; set; }
}
public partial class department
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public department()
{
this.section_detail = new HashSet<section_detail>();
}
public int dept_id { get; set; }
public string description { get; set; }
public string cost_center_code { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<section_detail> section_detail { get; set; }
}
public class EmployeeViewModel
{
public int section_detail_id { get; set; }
public Nullable<int> parent_section_det_id { get; set; }
public Nullable<byte> page_code { get; set; }
public string cost_center_code { get; set; }
public string print_descrip { get; set; }
public Nullable<int> phone_id { get; set; }
public Nullable<int> employee_id { get; set; }
public static explicit operator EmployeeViewModel(List<section_detail> v)
{
throw new NotImplementedException();
}
public string first_name { get; set; }
. . .
public string Comments { get; set; }
public string email { get; set; }
public string description { get; set; }
public string area_code { get; set; }
public string phone_nbr { get; set; }
public string BU { get; set; }
}
Controller:
private vcpds_test1Entities db = new vcpds_test1Entities();
// GET: EmployeeList
public ActionResult Index()
{
List<section_detail> employeeList = db.section_detail.ToList();
List<EmployeeViewModel> employeeVMList = employeeList.Where(emp => emp.page_code == 3)
.Select(emp => new EmployeeViewModel
{
last_name = emp.last_name,
first_name = emp.first_name,
employee_id = emp.employee_id,
phone_nbr = "(" + emp.phone.area_code + ") " + emp.phone.phone_nbr.Substring(0, 3) + "-" + emp.phone.phone_nbr.Substring(3, 4),
BU = emp.phone.BU,
description = emp.department.description,
page_code = emp.page_code
}).OrderBy(emp => emp.last_name).ThenBy(emp => emp.first_name).ToList();
return View(employeeVMList);
}
I get these messages:
System.NullReferenceException: 'Object reference not set to an instance of an object.'
VCPDS2.Models.section_detail.department.get returned null.
If I comment out description = emp.department.description from the controller, then it will return data from the section_detail and phone tables. I've checked the database and the relationships seem ok. I've tried refreshing the models from the database with no change.
It's possible that a emp doesn't have a department so it in itself is null. Description can't be a property of a null. So, what you can simply do is check if it is null first by using null operator:
...
//description = emp.department.description,
description = emp.department?.description ?? "",
...
Basically, if department itself is null, it will stop checking right there, and the ?? shortcut is to use the statement on the right side which is "" if the statement on the left is null.
If you were not expecting an emp not to have a department, you may need to revise your query
Quick edit: You probably need to use an Include in your query so it can bring the department's properties (for description):
List<section_detail> employeeList = db.section_detail
.Include(x => x.department)
.ToList();
I'm displaying the data from a table called gigs, however it contains a couple of foreign keys to tables 'Bands' and 'Venues' so when using this code in my controller,
string user = User.Identity.GetUserId();
var yourgigs = (from g in dbg.gigs
from v in dbg.Venues
from b in dbg.Bands
from ga in g.gigsaccasses
where (ga.Id == user &&
v.venueid == g.venueid &&
b.bandid == g.bandid)
select g);
return View(yourgigs);
it's displaying bandid and venueid in the view which are meaningless integers. How would I replace those with what I suppose would be b.bandname, v.venuename and also add v.address1 and v.city? The SQL statement that does this is
SELECT bands.bandname, venues.venuename, venues.address1, venues.city, gigs.whatdate, gigs.starttime
FROM gigs INNER JOIN
bands ON gigs.bandid = bands.bandid INNER JOIN
gigsaccass ON gigs.gigid = gigsaccass.gigid INNER JOIN
dbo.AspNetUsers ON gigsaccass.Id = dbo.AspNetUsers.Id INNER JOIN
venues ON gigs.venueid = venues.venueid
WHERE dbo.AspNetUsers.Id = //some user//
I did try using anonymous types as such:
var yourgigs = (from g in dbg.gigs
from v in dbg.Venues
from b in dbg.Bands
from ga in g.gigsaccasses
where (ga.Id == user &&
v.venueid == g.venueid &&
b.bandid == g.bandid
select new
{
bandname = b.bandname,
venuename = v.venuename,
address1 = v.address1,
city = v.city,
whatdate = g.whatdate,
starttime = g.starttime
});
But this then threw an error:
The model item passed into the dictionary is of type 'System.Data.Entity.Infrastructure.DbQuery1[<>f__AnonymousType76[System.String,System.String,System.String,System.String,System.DateTime,System.TimeSpan]]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[OnStageTonight_MVC.Models2.gigs]'.
The View is expecting type 'gigs'
#model IEnumerable<OnStageTonight_MVC.Models2.gigs>
#{
ViewBag.Title = "Gigs";
}
<h2>Gigs</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.venueid)
</th>
<th>
#Html.DisplayNameFor(model => model.bandid)
</th>
What am I missing?
EDIT:
I should add that I do have a model, but I'm assuming this is what is at fault.
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;
using System.Web;
namespace OnStageTonight_MVC.Models2
{
[Table("gigs")]
public partial class gigs
{
public gigs()
{
this.gigsaccasses = new HashSet<gigsaccass>();
}
[Key]
public int gigid { get; set; }
public int venueid { get; set; }
public int bandid { get; set; }
[Display(Name="Date")]
public System.DateTime whatdate { get; set; }
[Display(Name="Starts at")]
public System.TimeSpan starttime { get; set; }
public virtual ICollection<gigsaccass> gigsaccasses { get; set; }
}
[Table("gigsaccass")]
public partial class gigsaccass
{
[Key]
public int gigaccassid { get; set; }
public int gigid { get; set; }
public string Id { get; set; }
public virtual gigs gig { get; set; }
public virtual AspNetUsers AspNetUser { get; set; }
}
[Table("dbo.AspNetUsers")]
public class AspNetUsers
{
[Key]
public string Id { get; set; }
public string Email { get; set; }
public bool EmailConfirmed { get; set; }
public string PasswordHash { get; set; }
public string SecurityStamp { get; set; }
public string PhoneNumber { get; set; }
public bool PhoneNumberConfirmed { get; set; }
public bool TwoFactorEnabled { get; set; }
public Nullable<System.DateTime> LockoutEndDateUtc { get; set; }
public bool LockoutEnabled { get; set; }
public int AccessFailedCount { get; set; }
public string UserName { get; set; }
public string YourName { get; set; }
public List<gigsaccass> gigsaccasses { get; set; }
}
[Table("venues")]
public partial class venues
{
[Key]
public int venueid { get; set; }
[Required]
[Display(Name = "Venue")]
public string venuename { get; set; }
[Required]
[Display(Name = "Address")]
public string address1 { get; set; }
[Required]
[Display(Name = "City")]
public string city { get; set; }
public List<gigs> venuegigs { get; set; }
}
[Table("bands")]
public class bands
{
[Key]
public int bandid { get; set; }
[Required]
[Display(Name = "Name")]
public string bandname { get; set; }
public List<gigs> bandgigs { get; set; }
}
public partial class gigscontext : DbContext
{
public gigscontext()
: base("DefaultConnection")
{
}
public DbSet<gigs> gigs { get; set; }
public DbSet<gigsaccass> gigsaccass { get; set; }
public DbSet<AspNetUsers> AspNetUsers { get; set; }
public DbSet<venues> Venues { get; set; }
public DbSet<bands> Bands { get; set; }
}
}
You can't use anonymous classes here. Your view needs to know how to work with model, it needs type information, but: "The type name is generated by the compiler and is not available at the source code level"
You can't pass such objects around. http://www.codeproject.com/Articles/15624/Inside-C-Anonymous-Methods#5
You need to create class that represent row in your data set and return list of populated objects.
As less preferred alternative you can use dynamic: https://msdn.microsoft.com/en-us/library/dd264736.aspx
The M in MVC stands for model, and what you want is one of the 3 main tenants of MVC.
You want an object that encapsulates all the information to be displayed on the view.
It is considered best practice to create a model for the view. This is an additional layer which separates the storage of the item (your entity model) from it's presentation.
var yourgigs = (from g in dbg.gigs
from v in dbg.Venues
from b in dbg.Bands
from ga in g.gigsaccasses
where (ga.Id == user &&
v.venueid == g.venueid &&
b.bandid == g.bandid
select new GigViewModel
{
bandname = b.bandname,
venuename = v.venuename,
address1 = v.address1,
city = v.city,
whatdate = g.whatdate,
starttime = g.starttime
});
public class GigViewModel
{
public string bandname { get; set; }
public string venuename { get; set; }
public string address1 { get; set; }
public string city { get; set; }
public DateTime whatdate { get; set; }
public Timespan starttime { get; set; }
}
When persisting data from your view models, use AutoMapper or something similar to copy properties with matching names between your view models and your entity models.
Use the new view model in your view:
#model IEnumerable<OnStageTonight_MVC.Models2.GigModelView>
I'm building an application using ASP.NET MVC4 with code first data migrations. I have an estimates model, a clients model, a DbContext, and a view model I created. I am wanting to display the company name in a drop down, with the company name tied to an estimate. I have a ClientId in both models. I also created a DbSet<> and that didn't work either when querying against it.
I tried to create a viewmodel that I thought I could simply query against and display through my controller. I'm not having any luck in getting this to work. After a day plus of looking on here and other places, I'm out of ideas.
How can I query/join the two models, or query the viewmodel to get the company name associated with the clientId? Thanks for the help.
Models:
public class Estimates
{
[Key]
public int EstimateId { get; set; }
public int ClientId { get; set; }
public decimal EstimateAmount { get; set; }
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM/dd/yyyy}")]
public DateTime EstimateDate { get; set; }
public string EstimateNotes { get; set; }
}
public class Clients
{
[Key]
public int ClientId { get; set; }
public string CompanyName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
public ICollection<Estimates> Estimates { get; set; }
public ICollection<Contracts> Contracts { get; set; }
}
public class ClientEstimateViewModel
{
public Clients Clients { get; set; }
public Estimates Estimates { get; set; }
}
public class NovaDb : DbContext
{
public NovaDb(): base("DefaultConnection")
{
}
public DbSet<Clients> Clients { get; set; }
public DbSet<Estimates> Estimates { get; set; }
public DbSet<Contracts> Contracts { get; set; }
public DbSet<Invoices> Invoices { get; set; }
public DbSet<ClientEstimateViewModel> ClientViewModels { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
Controller:
NovaDb _db = new NovaDb();
ClientEstimateViewModel ce = new ClientEstimateViewModel();
public ActionResult Index()
{
var model =
(from r in ce.Clients
join x in ce.Estimates
where
//var model =
// from r in _db.Clients
// orderby r.CompanyName ascending
// select r;
return View(model);
}
Because you've created the relationship between client & estimate in your models, you should be able to create a query like this:
var query = from c in _db.clients
select new ClientEstimateViewModel
{
Clients = c,
Estimates = c.Estimates
}
Although you'd have to change your model so Estimates was public List<Estimates> Estimates { get; set; }
This would give you a collection of ClientEstimateViewModel which you could then pass to your view
I have set up 3 models, code first and the relationships seem to be working but one is causing me a problem.
I have Article, Language and Edition Classes
public class Article
{
public int ID { get; set; }
public string Name { get; set; }
public string Icon { get; set; }
}
public class Language
{
public int ID { get; set; }
public string Name { get; set; }
public string Code { get; set; }
}
public class Edition
{
public int ID { get; set; }
public Article Article { get; set; }
public Language Language { get; set; }
public string Title { get; set; }
public string Details { get; set; }
}
In my bootstrap/DBinitialiser, I can create Objects and populate them fine. The DB is created and the foreign keys for Language and Article are both present on the Edition table and correctly entered.
var engLang = new Language() {Code="en", Name="English Language"};
var altLang = new Language() {Code="xx", Name="Alternative Language"};
db.Languages.Add(engLang);
db.Languages.Add(altLang);
db.SaveChanges();
var testArt = new Article() { Name = "test" };
db.Articles.Add(testArt);
db.SaveChanges();
db.Editions.Add(new Edition(){Article = testArt, Language = engLang, Title="English Content"});
db.Editions.Add(new Edition(){Article = testArt, Language = altLang, Title="Alternative Content"});
db.SaveChanges();
I can now query the Editions and return a list of them, but the Language attribute is always NULL. The Article Attribute works fine.
var query = db.Editions.Where(r => r.Article.ID == Article.ID);
foreach (Edition item in query)
{
// item.Language => NULL
// item.Article => {Object Article}
}
I'm new to .net and Entity-Framework and can't work out why I always get this error.
I can even query by r => r.Language.ID == 1 and still get a NULL attribute on the Edition object.
Make sure you are using EF codefirst in right manner. Here you have some ambiguities. You must determine what relationships actually should exist, in your POCOs. Change classes like bellow:
public class Article
{
[Key]
public int ID { get; set; }
public string Name { get; set; }
public string Icon { get; set; }
}
public class Language
{
[Key]
public int ID { get; set; }
public string Name { get; set; }
public string Code { get; set; }
}
public class Edition
{
[Key]
public int ID { get; set; }
public virtual Article Article { get; set; }
public virtual Language Language { get; set; }
public string Title { get; set; }
public string Details { get; set; }
}
With thanks to AmirHossein Mehrvarzi for helping me write my models more clearly, I believe this error to be caused by the lazy loading of entities while iterating through the result of the query. ref: Entity Framework: There is already an open DataReader associated with this Command.
Without enabling MultipleActiveResultSets I simply added an Include statement to my linq
var query = db.Editions.Where(r => r.Article.ID == Article.ID).Include(r => r.Language);
foreach (Edition item in query)
{
// item.Language => {Object Language}
// item.Article => {Object Article}
}