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
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
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.
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; }
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
}
);
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; }