Mapping lists with Automapper - c#

I am using code first migrations for creating entities. My entities look like that:
public class User
{
private string userWholeName = string.Empty;
private ICollection<UsersInRoles> usersInRoles;
public User()
{
this.UserId = Guid.NewGuid();
this.usersInRoles = new System.Collections.Generic.HashSet<UsersInRoles>();
}
[Key]
public Guid UserId { get; set; }
//TODO: check for resource names and for all models
[Required(AllowEmptyStrings = false, ErrorMessage = null)]
public string UserName { get; set; }
[Required(AllowEmptyStrings = false)]
[MaxLength(30)]
public string Password { get; set; }
public virtual ICollection<UsersInRoles> UsersInRoles
{
get { return this.usersInRoles; }
set { this.usersInRoles = value; }
}
}
My UsersInRolesClass:
public class UsersInRoles
{
public UsersInRoles()
{
}
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int UsersInRolesId { get; set; }
public Guid UserId { get; set; }
public int RoleId { get; set; }
public virtual Role Role { get; set; }
public virtual User User { get; set; }
}
My Role class:
public class Role : Interfaces.IRole
{
private ICollection<UsersInRoles> usersInRoles;
public Role()
{
this.usersInRoles = new HashSet<UsersInRoles>();
}
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int RoleId { get; set; }
[Required]
public string RoleName { get; set; }
public string RoleDescription { get; set; }
public virtual ICollection<UsersInRoles> UsersInRoles
{
get
{
return this.usersInRoles;
}
set
{
this.usersInRoles = value;
}
}
}
So those are my db entities. I am trying to map them to:
public class UserDTO
{
//other properties same as in User entity
IList<RoleDTO> Roles { get; set; }
}
public class RoleDTO
{
int RoleId { get; set; }
string RoleName { get; set; }
}
Every property is mapped, but Roles are not. I am trying this:
Mapper.Initialize(cfg => cfg.CreateMap<UserDTO, User>().ForMember(dest => dest.UsersInRoles, opt => opt.ResolveUsing(c=>c.Roles.Select(f=>new UsersInRoles() { Role = new Role() { RoleId = f.RoleId,RoleName = f.RoleName}, RoleId = f.RoleId,UserId = c.UserId }))));
Any Ideas ?

Related

How to connect Asp.Nets database with my own context?

I'm trying to build an application in Mvc with Individual User Accounts, and I'm trying to connect the automatically generated database with my own context.
The problem I have when I trying to create a view of my Create method I get this errormessage:
There was an error running the selected code generator: 'Unable to
retrieve metadata for 'Projekt_Dejtingsida.Models.Messages' is not
valid. The navigation property 'ApplicationUser' was not found on the
dependent type 'Projekt_Dejtsida.Models.Messages'. The Name value
should be a valid navigation property name.
Please help a beginner out!
Here are the models I'm using:
I have already tried the protected override void OnModelCreating(DbModelBuilder modelBuilder) method, but it didn't work...
public class Messages {
[Key, ForeignKey("ApplicationUser")]
public string Id { get; set; }
[Key]
public int MessageId { get; set; }
public virtual ApplicationUser Sender { get; set; }
public virtual ApplicationUser Receiver { get; set; }
[Required(AllowEmptyStrings = false, ErrorMessage = "You can't send a message without a content")]
[StringLength(300, MinimumLength = 3, ErrorMessage = "Your message should be between 3 and 300 characters")]
public string MessageContent { get; set; }
}
public class FriendRequests {
public string UserId { get; set; }
[Key]
public int RequestId { get; set; }
public virtual ApplicationUser RequestTo { get; set; }
public virtual ApplicationUser RequestFrom { get; set; }
public bool Confirmed { get; set; }
}
public class Profile {
[Key]
public string UserId { get; set; }
public byte[] ProfilePicture { get; set; }
public string Firstname { get; set; }
public int Age { get; set; }
public string Gender { get; set; }
public string City { get; set; }
public string About { get; set; }
public virtual ICollection<Messages> MyMessages { get; set; }
}
Here is the DbContext:
public class DatesiteContext : DbContext {
public DatesiteContext() : base() { }
public DbSet<FriendRequests> Requests { get; set; }
public DbSet<Messages> Messages { get; set; }
public DbSet<Profile> Profiles { get; set; }
}
Here is the MessageController
[Authorize]
public class MessageController : Controller
{
// GET: Message
public ActionResult Index()
{
var db = new DatesiteContext();
var userId = User.Identity.GetUserId();
var msgs = db.Messages.FirstOrDefault(m => m.Id == userId);
return View(new MessageViewModel {
Sender = msgs.Sender,
Receiver = msgs.Receiver,
MessageContent = msgs.MessageContent
});
}
public ActionResult Create(MessageViewModel model) {
DatesiteContext db = new DatesiteContext();
var userId = User.Identity.GetUserId();
var msgs = db.Messages.FirstOrDefault(m => m.Id == userId);
if (msgs == null) {
db.Messages.Add(new Messages {
Id = userId,
Sender = msgs.Sender,
Receiver = msgs.Receiver,
MessageContent = msgs.MessageContent
});
} else {
msgs.Sender = model.Sender;
msgs.Receiver = model.Receiver;
msgs.MessageContent = model.MessageContent;
}
db.SaveChanges();
return RedirectToAction("Index", "Profile");
}
}

How to map a List in Entity Framework?

I have two classes: Role and RoleViewModel.
Role class
public partial class Role
{
public Role()
{
this.Users = new HashSet<User>();
}
public int RoleId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<User> Users { get; set; }
}
RoleViewModel class
public class RoleViewModel
{
public RoleViewModel()
{
this.Users = new HashSet<UserViewModel>();
}
public int RoleId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<UserViewModel> Users { get; set; }
}
Now, I am trying to fetch a list of Role from database and map it to a list of RoleViewModel.
public static List<RoleViewModel> GetRolesService()
{
List<Role> roles =MainRepository.GetUserRoles();
var rolesVM = Mapper.Map<List<Role>, List<RoleViewModel>>(roles);
return rolesVM;
}
The problem is that rolesVM list always have Count=0, and I don't know why.
Thanks in advance!.
One solution is to ignore nested dependencies.
Mapper.CreateMap<Role, RoleViewModel>().ForMember(c=>c.Users,option=>option.Ignore());

Handling composite keys in db table

I have a table called UsersInRoles with 2 X foreign keys as a composite key which doubles up as the primary key for this 2 column table. Just for resolving many-to-many. So within Entity Framework 6 I have the dal classes.
public partial class User
{
public User()
{
this.Roles = new HashSet<Role>();
}
public int UserId { get; set; }
public int ApplicationId { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public bool IsAnonymous { get; set; }
public System.DateTime LastActivityDate { get; set; }
public virtual Application Application { get; set; }
public virtual ICollection<Role> Roles { get; set; }
}
public partial class Role
{
public Role()
{
this.Users = new HashSet<User>();
}
public int RoleId { get; set; }
public int ApplicationId { get; set; }
public string RoleName { get; set; }
public string Description { get; set; }
public virtual Application Application { get; set; }
public virtual ICollection<User> Users { get; set; }
}
So I need to get at the fields within my composite table. I wondered if anyone can provide me with assistance on how to resolve this within OnModelCreating in the dbcontext. So that I can then do something with hasKeys
If you only need to change the Id's name or the table's name you can do that with this configuration:
modelBuilder.Entity<User>()
.HasMany(u => u.Roles)
.WithMany(r => r.Users)
.Map(cs =>
{
cs.MapLeftKey("UserRefId");
cs.MapRightKey("RoleRefId");
cs.ToTable("UsersInRoles");
});
Now if you need to get access explicitly to the junction table or you need to add it new columns, unfortunately you'll need to map it as part of your model.
public partial class User
{
public User()
{
this.Roles = new HashSet<Role>();
}
public int UserId { get; set; }
//...
public virtual ICollection<UsersInRoles> Roles { get; set; }
}
public partial class Role
{
public Role()
{
this.Users = new HashSet<User>();
}
public int RoleId { get; set; }
public virtual ICollection<UsersInRoles> Users { get; set; }
}
public class UsersInRoles
{
[Key, Column(Order = 0),ForeignKey("User")]
public int UserId { get; set; }
[Key, Column(Order = 1),ForeignKey("Role")]
public int RoleId { get; set; }
public virtual User User { get; set; }
public virtual Role Role { get; set; }
//add new properties here
}
If you prefer use Fluent Api, then remove the data annotations and add these configurations in the OnModelCreating method on your context:
modelBuilder.Entity<UsersInRoles>()
.HasKey(ur=> new { ur.UserId, ur.RoleId});
modelBuilder.Entity<UsersInRoles>()
.HasRequired(ur=> ur.User)
.WithMany(u => u.Roles)
.HasForeignKey(ur=> ur.UserId);
modelBuilder.Entity<UsersInRoles>()
.HasRequired(ur=> ur.Role)
.WithMany(u => u.Users)
.HasForeignKey(ur=> ur.RoleId);

ASP.NET MVC model from db

I created my model from DB in which I have tables Users, Roles and UsersInRoles which is an intermediary table between the first 2.
My question is how do I take specific users where Roles = something since the table UsersInRoles is not added to the model?
public partial class Role
{
public Role()
{
this.Users = new HashSet<User>();
}
public int RoleID { get; set; }
public string RoleName { get; set; }
public string RoleDescription { get; set; }
public virtual ICollection<User> Users { get; set; }
}
public partial class User
{
public User()
{
this.Roles = new HashSet<Role>();
}
public int UserID { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual ICollection<Role> Roles { get; set; }
}
public ActionResult Index()
{
var users = db.Users;
return View(users.ToList());
}
I believe this will work...
var usersInRole = db.Users.Where(x => x.Roles.Any(y => y.RoleId == roleid));
I admittedly haven't had much experience with HashSets, but is there any reason a simple Linq query wouldn't work?
var requestedUsers = from UsersInRoles
in db.Users
where UsersInRoles.Roles.Contains(DesiredRoleHere)
select UsersInRoles;

Add value to one object in EF

I have a function:
public void Add(User user)
{
var id = WebSecurity.CurrentUserId;
//add id to FK CUserID
context.User.Add(user);
}
I'm adding user data to database. How to add id value to CUserID?
public class User
{
[key]
public int UserID { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public string E-mail { get; set; }
public UserProfile CUserID { get; set; }
}
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int CUserId { get; set; }
public string UserName { get; set; }
}
EDIT:
If I try do:
user.CUserId = id;
I get an error:
Cannot implicitly convert type 'int' to 'Project.Models.UserProfile'
Change the User class:
public class User
{
[key]
int UserID { get; set; }
string Name { get; set; }
string Surname { get; set; }
string E-mail { get; set; }
[ForeignKey("UserProfile)]
int CUserID { get; set; }
virtual UserProfile UserProfile { get; set; ]
}
Now you can set the ID value and entity framework will get the matching UserProfile when you save changes.
Going on what you've described in your question, try this:
public void Add(User user)
{
using (var context = new MyDbContext())
{
var currentUser = context.UserProfile.Single(
u => u.UserName == System.Web.HttpContext.Current.User.Identity.Name);
var newUser = new User();
newUser.Name = user.Name;
newUser.Surname = user.Surname;
newUser.Email = user.Email;
newUser.CUserID = currentUser.CUserId;
context.User.Add(newUser);
context.SaveChanges();
}
}

Categories

Resources