How I can use Include of the LINQ properly under MVC3?
I created .edmx file and it has all tables.
Two of them have a relashionships
UserCategories 1..0 - * Users
I guessed to use
var userCategories = db.UserCategories.Include("Users");
in order to populate Users property. But it is always empty.
(Here there is a good example how to use it. But no success.)
How do I can fix it?
P.S. POCO class
public partial class UserCategory
{
public UserCategory()
{
this.Users = new HashSet<User>();
}
public string Name { get; set; }
public System.Guid ID { get; set; }
public virtual ICollection<User> Users { get; set; }
}
Ok, first if Users it's empty probably it's because your don't have the data in the database. Now to be specific refactor your expression like this
var userCategories = db.UserCategories.Select(x => x.Users).ToList();
This will retrieve all the users in your database which have a relation with the table UserCategory
If you just tried to obtain the users no matter the relation with the table
var users = db.Users.ToList(); // This retrieve all the users in your database
Disclaimer: note that this expressions are heave and bring all the records of your database used carefully
Class Model
{
private int userName;
.....
public UserName{get{return userName;} set{userName= value;}}
....
}
I am assuming that Model is the passing model and it has a UserName attribute. And there is a userName column in Users Table.
private dbContext db = new dbContext();
public List<Model> method(){
List<Model> m= List<Model>()
var userCategories = db.UserCategories.Include("Users");
return from item in userCategories select new Model
{
UserName = item.Users.userName
.......
}
}
This return value will be a IEnumerable<Model> it will be executed in foreach. So the
Related
hello all i am new to entity and asp.net M.V.C i am using entity framework code first approach with already made database i want to show three tables data in a table using inner join and confused how to do it
i have tried the following code given below
public List<NewGroupRoles> GetAllGroups()
{
try
{
using(var p=new VMSDBContext())
{
var group = (from group_role in p.group_roles
join groups in p.groups on group_role.group_id equals groups.group_id
join roles in p.roles on group_role.roles_id equals roles.role_id
select new
{
Id = group_role.group_roles_id,
group_name = groups.group_name,
group_role = roles.role_name
}).ToList();
}
}
catch(Exception ex)
{
return new List<NewGroupRoles>();
}
}
i want to return it from a function in model
model classes areths class defines all the database entity classes
this a group table
[this is group role class][3]
role class
You are trying to do work, which EF is supposed to do for you.
It looks like you have many-to-many relationship between the groups and roles tables. Why wouldn't you remove the group_roles class and just define navigation properties
public virtual IEnumerable<roles> roles { get; set; }
in groups model class and
public virtual IEnumerable<groups> groups { get; set; }
in roles model class
and get list of groups and roles somehow like this:
var groupRoles = p.groups.SelectMany(g=>g.roles, (g,r)=>new {Group = g.group_name, Role = r.role_name}).ToList();
Or if your use EF Core, which yet does not support many-to-many relationships without intermediate model class or just insist on having an intermediate class group_roles in your model, you can define two navigation properties in it, something like this:
public class group_roles
{
[Key]
public int group_roles_id { get; set; }
[ForeignKey("groups")]
public int group_id { get; set; }
[ForeignKey("roles")]
public int role_id { get; set; }
public virtual groups group { get; set; }
public virtual roles role { get; set; }
}
Then your query is just
var groupRoles = p.group_roles.Select(gr=> new {gr.group_roles_id, Group=gr.group.group_name, Role=gr.role.role_name).ToList();
Use this as you need to have new object while selecting
public List<NewGroupRoles> GetAllGroups()
{
try
{
using(var p=new VMSDBContext())
{
var group = (from group_role in p.group_roles
join groups in p.groups on group_role.group_id equals groups.group_id
join roles in p.roles on group_role.roles_id equals roles.role_id
select new NewGroupRoles()
{
Id = group_role.group_roles_id,
group_name = groups.group_name,
group_role = roles.role_name
}).ToList();
}
}
catch(Exception ex)
{
return new List<NewGroupRoles>();
}
return group;
}
Until now I have always worked with my own DAL for SQL Server.
In a new project I decided to work with Entity in a MVC project and Identity.
I use to work with bridge tables.
Here is my IdentityModels (simplified)
ApplicationUser
public class ApplicationUser : IdentityUser
{
[Required]
public string Surname { get; set; }
[Required]
public string Name { get; set; }
public virtual ICollection<Group> Groups { get; set; }
}
Group
public class Group
{
[Key]
public int Id { get; set; }
[Display(Name = "Nom du Groupe")]
[Required]
[CustomRemoteValidation("IsGroupNameExist", "Groups", AdditionalFields =
"Id")]
public string Name { get; set; }
public virtual ICollection<ApplicationUser> ApplicationUsers { get; set;
}
And DbContext
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
public DbSet<Group> Groups { get; set; }
}
All tables I need are created and seems well created (ApplicationUser Group and ApplicationUserGroups).
The trouble is :
I have 3 groups (A, B, C) with Id 1,2,3. I"m adding a user in table ApplicationUser with 3 groups in the Groups property.
First part is OK, it adds the good values in the bridge table (ApplicationUsersGroup) BUT It adds groups A, B, C again, with Id 4,5,6 in Group table.
The CreateAsync method of UserManageris not the point (It's the same with just an Add).
If I have a look in the debugger, I can see that when I pass to the add method the user object, in the Groupsproperty, I have a ApplicationUsers property with inside the Groups property. For me, it could be the reason, but if I remove the Groups property from ApplicationUser, code first doesn't create the ApplicationUserGroups.
I'm wrong with something, but what? How can I have a user without an additional entry in Grouptable?
Thank you for your help.
UPDATE
Ok, now I understood why duplicates are added, but in my case, how to avoid that?
Here is the involved part of the Register method:
List<Group> selectedItems = new List<Group>();
foreach (GroupTableViewModel item in model.SelectedGroups)
{
if (item.Selected == true) selectedItems.Add(new Group { Id = item.Id, Name = item.GroupName });
}
var user = new ApplicationUser { Name = model.Name, Surname = model.Surname, UserName = model.Surname + "." + model.Name, Email = model.Email,Groups=selectedItems};
string password = RandomPassword.Generate(8, 8);
var result = await UserManager.CreateAsync(user, password);
CreateAsync() is the identity method. I don't understand how it adds the user (I don't see any Add() or 'SaveChanges() inside with JustDecompile).
Maybe I'm wrong again but if I want to attach an entity to the context I have to create a new context, which will be different from the context used by the CreateAsync() method.
So help needed...
This is a common issue that people unfamiliar with EF face. Because of the disconnected state of entities in the object context, EF will attempt to insert the entities in the relationships, even though they already exist. In order to solve, you need to tell EF that the entities are not new by setting their state to Unchanged. Take a look at this article from Julie Lerman and the related SO question/answer.
https://msdn.microsoft.com/en-us/magazine/dn166926.aspx
Entityframework duplicating when calling savechanges
I refer to the answer here (https://stackoverflow.com/a/20846170/1753877) about how to insert a record into the Users_Friends lookup table in this type of relationship
The answer is :
var user = db.Users.Find(userID);
var friend = db.Friends.Find(friendID);
user.Friends.Add(friend);
db.SaveChanges();
However, to me it seems like a lot of overhead to have to retrieve two objects from the database just to insert a row comprising of just the two IDs that are already known to the application without the need for any queries.
Could we not just do a basic INSERT using userID and friendID as values (or pass them to a stored procedure to do the same).
As I am new to Entity Framework, I'm unsure if there are any advantages to using the code above that would be missed with a direct SQL INSERT, or if there is a valid reason to avoid using direct SQL with Entity framework for inserts
Thanks.
There are several ways to do this:
first is if User_Friends has its own entity you can just populate a new user_friends with the id's and save changes.
The second is to create a New friend and user and attach them (something similar to this, may take some tweaking):
var friend = new Friend{Id = friendID};
var user = new User{Id = userID};
using (var context = new Context())
{
context.Friends.Attach(friend);
user.Friends.Add(friend);
context.Entry(user).State = EntityState.Modified;
context.SaveChanges();
}
Entity Framework Add and Attach and Entity States
The third is to use Context.Database and either execute sql command or sql query (depending) to execute arbitrary SQL against the database.
What I have found the easiest is to include User_Friends as its own EF entity and create a new one. It makes adding to the union table very easy.
You could do a direct insert like:
db.Database.ExecuteSqlCommand(#"insert into Users_friends
(UserId, FriendId) values ({0}, {1})", userID, friendID);
I don't see an advantage first retrieving the values from db (except verifying both user and friend exists). However, in the above code there is no check if userID, friendID pair already exists which could be easily added to SQL.
You are correct that it is a lot needless overhead. In Entity Framework, it's enough to just pass a new instance of the class with the PK loaded:
var user = db.Users.Find(userID);
var friend = new Friend { Id = friendID };
user.Friends.Add(friend);
db.SaveChanges();
Create the bridge table as a model as well, like this
public class User
{
public int Id { get; set; }
public string Username { get; set; }
public string PasswordHash { get; set; }
public string PasswordSalt { get; set; }
public List<UserFriend> Friends { get; set; }
public User()
{
Friends = new List<UserFriend>();
}
}
public class Friend
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class UserFriend
{
public int Id { get; set; }
public int UserId { get; set; }
public int FriendId { get; set; }
[ForeignKey("UserId")]
public User User { get; set; }
[ForeignKey("FriendId")]
public Friend Friend { get; set; }
}
Then you can create or get user friends like this
// add user friend
var userFriend = new UserFriend()
{
UserId = userId,
FriendId = friendId
};
db.UserFriends.Add(userFriend);
db.SaveChanges();
// get user friends
db.Users.Include("Friends").ToList();
I would like to know if there is a way to add two linked objects to a database through entity framework before the linked field has been generated by the database.
I am still learning EF and I'm not exactly sure how to ask this question clearly so here is an example of what I am trying to achieve:
I have two classes:
class Sale
{
public int Id { get; set; } // generated by SQL Server
public string Foo { get; set; }
public string Bar { get; set; }
public virtual ICollection<SalesComment> Comments { get; set; }
}
class SalesComment
{
public int Id { get; set; }
public int SaleId { get; set; }
public string Comment {get; set; }
}
Using fluent api in my 'dbcontext' class I link the two objects like so:
modelBuilder.Entity<Sale>().HasMany(s => s.Comments).WithRequired().HasForeignKey(c => c.SaleId);
This works great, I can retrieve a Sale object from the database and I can loop through the comments linked to it by SaleId.
What I want to do is when creating a new Sale, add a Comment as I am creating it, with EF realising this is happening and adding the SaleId to the Comments table once it is generated by the database, something like:
using (MyDatabase db = new MyDatabase())
{
var sale = db.Set<Sale>();
sale.Add(new Sale
{
Foo = "Test",
Bar = "Test",
Comment.Add(new SalesComment .... //this is the line i'm not sure about
});
db.SaveChanges();
}
Is something like this possible? Or would I have to first save the Sale object to the database so that a SaleId is generated, then retrieve that object again so I can read the SaleId to use for a new SalesComment.
Try this.
using (MyDatabase db = new MyDatabase())
{
var sale = db.Set<Sale>();
var saleComment = new SalesComment{Comment="Hello"};
var saleToAdd = new Sale
{
Foo = "Test",
Bar = "Test",
Comments = new List<SalesComment> {saleComment}
});
sale.Add(saleToAdd);
db.SaveChanges();
// After saving changes, these 2 values will be populated and are equal
var saleID = saleToAdd.Id;
var saleCommentSaleId = saleComment.saleId;
}
You don't have to retrieve the object again if you cache it properly before adding it to the DbSet.
I have two EF models/classes that have relation between them: Member and MembershipSeason. One Member can have several MembershipSeasons. One MembershipSeason model has a foreign key reference (MemberID) to Member model in db.
Member.cs
public class Member
{
public int MemberID { get; set; }
//some properties left out
public virtual ICollection<MembershipSeason> MembershipSeasons { get; set; }
}
MembershipSeason.cs
public class MembershipSeason
{
[Key]
public int MembershipSeasonID { get; set; }
//some properties left out
public int MemberID { get; set; }
public virtual Member Member { get; set; }
}
I experimented to post those two models to the same Create method together in the same time. I discovered that EF tracks those two models and saves them into db as new models. It also links those two models by setting MemberID of the new Member model as foreign key to the new MembershipSeason model in db. I guess this is planned behaviour? – I mean the fact EF sets foreign key to the related models automatically seems to be expected behaviour – how things should work. Therefore I guess I don’t need to save Member model first, obtain it’s MemberID and use it for MembershipSeason and save it separately in the Create method? (because EF does the work for you)
db.Members.Add(member);
db.MembershipSeasons.Add(membershipSeason);
await db.SaveChangesAsync();
The above and the below Create method works in the way that no MemberID property is needed to be set directly to MembershipSeason model, because EF does it automatically.
MemberController.cs
public class MemberController : Controller
{
private MembersContext db = new MembersContext();
//some code left out
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create([Bind(Include = "MemberNumber,FirstName,LastName")] Member member,
[Bind(Include = "HasPaidMembership,SeasonId")] MembershipSeason membershipSeason)
{
try
{
if (ModelState.IsValid)
{
db.Members.Add(member);
db.MembershipSeasons.Add(membershipSeason);
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
}
catch (DataException /* dex */)
{
}
return View(member);
}
}
I am quite new with EF and ASP.NET MVC, so I am trying to figure these things out. Any help appreciated – thanks.
It also links those two models by setting MemberID of the new Member model as foreign key to the new MembershipSeason model in db. I guess this is planned behaviour?
TL;DR: Yes
Yes, it has to be the required behavior. Lets start with reads:
public class Organization
{
public Guid Id { get; set; }
}
public class Employee
{
public Guid Id { get; set; }
public Guid OrganizationId { get; set; }
public Organization Organization { get; set; }
}
public Employee GetEmployeeWithOrganization(guid id)
{
var result = _context.Employees
.Include(e => e.Organization)
.FirstOrDefault(e => e.Id = id);
}
Basically when you ask EF to include the navigation property you'd get an object graph kinda like:
Employee
- Id : <guid1>
- OrganizationId : <guid2>
- Organization : object
- Id : <guid2>
It would be common sense to assume that because EF should keep track of entities because what happens if you do this:
var employee = GetEmployeeWithOrganization(<guid1>)
var org = new Organization { id = guid.NewGuid() }; //<guid3>
employee.Organization = org;
_context.SaveChanges();
Which one of these is a valid object:
A:
Employee
- Id : <guid1>
- OrganizationId : <guid2> // <-- difference
- Organization : object
- Id : <guid3>
B:
Employee
- Id : <guid1>
- OrganizationId : <guid3> // <-- difference
- Organization : object
- Id : <guid3>
A isn't valid, because you can't rely on the values and programming against that object would not only be a completely nightmare, but at the database level doesn't make sense. B is valid, it is data you can rely on.
This also means you can precache items and EF will write them up automagically. Consider:
var org = GetOrganization(<guid3>);
var emp = GetEmployee(<guid1>);
Assert.That(emp.Organization, Is.Not.Null); // passes
This happens because EF is tracking org and because EF is configured with org as a FK to employee.