Asp.net mvc4 how to join entities by using linq - asp.net

I have a problem with joining two entities by linq language.
I have model Category:
public class Category : DbContext
{
[Key, Column(Order = 0),DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int CategoryId { get; set; }
Key, Column(Order = 1)]
public int ShopId { get; set; }
public string Name {get;set;}
public virtual ICollection<Parameter> Parameter { get; set; }
}
and model Parametr
public class Parameter : DbContext
{
[Key, Column(Order = 0),DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ParamId { get; set;}
[Key, Column(Order = 1)]
public int ShopId { get; set;}
public string Name {get; set;}
public string Value {get;set;}
}
The relation is one to many, so one Category coud have 0...n Parameters.
UPDATE:
Sure, the relationship is many to many. This is the reason, why Parameter has no CategoryId attribute in the model.
I'm using code first and migration tool for updataing database;
In database MSSQL Express are 3tables. Category, CategoryParameters and Parameters.
Table CategoryParameter was created automaticaly and I have no Model for this table.
Creating new Category with multiple Parameters working fine. All 3tables contains valid data.
So my problem now:
I'm trying to load all parameters for one Category. The command looks like:
var parameters = from c in db.Categories
join p in db.Parameters
on new { ??? , c.ShopId } equals new { ??? , p.ShopId }
where c.ShopId == userProfile.ShopId && c.CategoryId == id
select new { ParamId = p.ParamId, Name = p.Name };
So my problem is, how to hell join these tables, if there is no usable atribute in the classes.
Many thanks for any help!

You don't need JOIN: use navigation property instead:
Find the category entity.
Use Parameter property of the category entity.
var parameters = db.Categories.First(x => x.CategoryId == 10).Parameter.ToList();

Related

Selecting Posts of Users whom I am following

I have two models:
public class UserProfile {
public int Id { get; set; }
public virtual ICollection<UserProfile> Following { get; set; }
public virtual ICollection<Post> Posts { get; set; }
}
public class Post {
public int Id { get; set; }
public virtual UserProfile { get; set; }
}
I want to select all of the posts of the users that the current user is following. It's basically like showing a feed of the posts of people you follow on social networking websites. How do I do this in linq? Im getting an error with this.
var following = CurrentUser.UserProfile.Following;
var posts = (from p in db.Posts
where following.Any(a=>a.Id == p.UserProfile.Id)
select new Post).ToList();
You can use the navigation properties to get the result:
var result=CurrentUser.UserProfile.Following.SelectMany(u=>u.Posts);
I think the problem is you because you are trying to project your query to an entity class (Post). In EF you can only project a query to an anonymous type or a DTO (custom class).
Another way to do it following your idea is doing this:
var following = CurrentUser.UserProfile.Following.Select(u=>u.Id);
var posts = (from p in db.Posts
where following.Contains(p.UserProfile.Id)
select p).ToList();
Contains extension method is translated to an IN in SQL

Entity Framework Many To Many allow duplicates

Is it possible to insert duplicate rows in Many to Many relationship? This is my class:
public class EventPaintballBundle
{
[Key, Column(Order = 0)]
public int EventID { get; set; }
[Key, Column(Order = 1)]
public int PaintballBundleID { get; set; }
public virtual Event Event { get; set; }
public virtual PaintballBundle PaintballBundle { get; set; }
[Range(1, Int32.MaxValue)]
public int PersonCount { get; set; }
[Required]
public DateTime Data { get; set; }
}
I want to insert second row of those values. The differences are on Date Date and PersonCount value
EventPaintballBundle xx = new EventPaintballBundle() { PaintballBundleID = 1, EventID = 155, Data = DateTime.Now, PersonCount = 5 };
dc.EventPaintballBundles.Add(xx);
dc.SaveChanges();
I'm getting error while I want to insert a duplicate of two keys.
{"Violation of PRIMARY KEY constraint 'PK_dbo.EventPaintballBundles'.
Cannot insert duplicate key in object 'dbo.EventPaintballBundles'. The
duplicate key value is (155, 1).\r\nThe statement has been
terminated."}
How to solve this problem?
Create a primary key that isn't the combination of :
public int EventID { get; set; }
public int PaintballBundleID { get; set; }
The new primary should be unique and not related to anything that actually exist, this key will exist only to make your model work database wise.
It's a classic mistake : to think your primary key should represent something that exist... NO
I learned it the hard way : even if i think that some combination of existing data will stay forever unique. I don't use it. I ALWAYS create my primary key from my own design, not representing anything real.

Xamarin.Forms.Portable : How to display data that comes from 2 different Entities?

Good Day everyone. I'm currently creating a simple Xamarin.Forms Portable mobile application that allows me to input record of an Employee Name and Employee Department.
I was able to retrieve the employee records created from the ASP.NET Web application Database, and display it on a ListView in the UWP part of my program. However, the data being retrieved is just coming from a single Entity namely 'Employee'. How will I display records that comes from 2 different Entities?
I have tried it using this codes but wasn't able to do so. If you need to see more codes, just please let me know. Thanks a lot.
EmployeeController
private EmployeesContext db = new EmployeesContext();
public IQueryable<EmployeeVM> GetEmployees()
{
return from emp in db.Employees
join dept in db.Departments
on emp.Department_id equals dept.Id
select new EmployeeVM
{
Id = emp.Id,
Name = emp.Name,
Department_id = emp.Department_id,
Department_Name = dept.Department_Name
};
}
ViewModel
public class EmployeeVM
{
public int Id { get; set; }
public string Name { get; set; }
//public string Department { get; set; }
public int Department_id { get; set; }
public string Department_Name { get; set; }
}
EmployeesContext
public System.Data.Entity.DbSet<XamarinFormsDemo.Models.Employee> Employees { get; set; }
public System.Data.Entity.DbSet<XamarinFormsDemo.Models.Department> Departments { get; set; }

LINQ Group By Type for each user

I have a list of objects with following structure
public class Jobs
{
public string EmployeeName { get; set; }
public string JobNumber { get; set; }
public string JobPriority { get; set; }
public string JobType { get; set; }
public string Description { get; set; }
public string Status { get; set; }
public string CreatedByUser { get; set; }
public DateTime DueDate { get; set; }
public DateTime UpdateDate { get; set; }
}
What I would like to do is to return a List of objects which contains
EmployeeName,
Total Count of Jobs assigned to him,
Job Type & Count of each job type assigned to an emploee.
So in essence, I would need list of records to appear like the attached image below. I will use the result from the LINQ query and bind it to a asp.net GridView
Andrew
Total Jobs: 12
Build Jobs: 3
Config Jobs: 4
Delivery Jobs: 3
How can I achieve a result using the linq from the initial list that i have. I guess for pros, this would be a very simple and straight-forwad LINQ query.
EDIT: Added for final structure that i want:
I would like to get the result from LINQ into following structure. i.e. List of UserJob
public class UserJob
{
public string EmployeeName { get; set; }
public int TotalJobs { get; set; }
public List<UserJobGroup> Tickets { get; set; }
}
public class UserJobGroup
{
public string JobType { get; set; }
public int JobCount { get; set; }
}
dasblinkenlight already explained it. With your specific classes, it's even easier - all you need is to follow the steps he described and translate them to LINQ. You should really be able to do that yourself, especially with query syntax:
var result =
(from job in jobList
group job by job.EmployeeName into employeeNameJobs
let jobTypeJobs =
(from job in employeeNameJobs
group job by job.JobType into jobTypeJobs
select new UserJobGroup
{
JobType = jobTypeJobs.Key,
JobCount = jobTypeJobs.Count()
})
.ToList()
select new UserJob
{
EmployeeName = employeeNameJobs.Key,
TotalJobs = jobTypeJobs.Sum(item => item.JobCount),
Tickets = jobTypeJobs
})
.ToList();
Let's walk through the structure of the query that you are trying to build:
At the top level you need groups by employee
At the employee level you need two related, but separate, things:
You need separate counts by job, and
You also need the total of these counts
Now let's build the query. Start with GroupBy for the top level:
var empGroups = jobList.GroupBy(j => j.EmployeeName);
Convert each group to a dictionary with EmployeeName serving as the key, and job group counts stored as values:
var jobCountsByEmployee = empGroups
.ToDictionary(
g => g.Key
, g => g.GroupBy(j => j.JobType)
.ToDictionary(jg => jg.Key, jg => jg.Count())
);
Finally, add totals to construct the result that you want:
var res = jobCountsByEmployee
.ToDictionary(
p => p.Key
, p => new {
Total = p.Value.Sum(jc => jc.Value)
, CountByJob = p.Value
}
);

ASP.NET Entity Framework Code First, Model Classes with Complex-type Properties Can not be Recorded on Local Database

I have been a webforms guy for a long time but I think it is time to move to ASP.NET MVC programming.
During my studies of MVC I came accross this example of creating a music store. Everything was fine until section 4, where you are required to populate the database with some pre-defined data. I had the problem when I was trying to achieve that. Apparently the problem was when trying to write Album Model objects, which had Author and Genre types as properties, to localDB using Entity Framework Code-first approach.
http://www.asp.net/mvc/tutorials/mvc-music-store/mvc-music-store-part-4
Seems like I have a problem with the Album class structure. In the tutorial Album class has 2 complex types:
public Genre Genre { get; set; }
public Artist Artist { get; set; }
And when I try to record them in the dbcontext as below, nothing happens. No data is written:(code in SampleData.cs)
var albums = new List<Album>
{
new Album { Title = "Worlds", Genre = genres.Single(g => g.Name == "Rock"), Price = 8.99M,Artist = artists.Single(a => a.Name == "Accept"),BookArtUrl = "/Content/Images/placeholder.gif"
}
};
foreach (var al in albums)
{
context.Albums.Add(al);
}
But when I change the complex types in Album class to be strings:
public string Genre { get; set; }
public string Artist { get; set; }
I can record them as below:(code in SampleData.cs)
var albums = new List<Album>
{
new Album { Title = "Worlds", Genre = (genres.Single(g => g.Name == "Rock")).ToString(), Price = 8.99M,Artist = (artists.Single(a => a.Name == "Accept")).ToString(),BookArtUrl = "/Content/Images/placeholder.gif"
}
};
foreach (var al in albums)
{
context.Albums.Add(al);
}
I don't know why it worked in the tutorial but not my exercise.
Any help is appreciated.
Try making your object properties virtual (so they can be overriden by EF Code First):
public virtual Genre Genre { get; set; }
public virtual Artist Artist { get; set; }
You can also implicitly add GenreID and ArtistID foreign key fields and set a link to child entity manually (using attributes):
public int GenreID {get; set;}
public int ArtistID {get; set;}
[ForeignKey("GenreID")]
public virtual Genre Genre { get; set; }
[ForeignKey("ArtistID")]
public virtual Artist Artist { get; set; }

Resources