Object reference not set to an instance of an object. Adding User Entity Framework - entity-framework

The thing is I am new in Entity Framework and I must be missing something small.
Anyways, I have three tables and I am getting the error adding the user:
Users
Logins
ShippingProfiles
Relationship:
1 to 1 : Users - logins
1 to many: Users - ShippingProfiles
My code behind:
User user = new User();
user.AddUser(user, firstNameInput.Text, lastNameInput.Text, emailList, bdayInput.Text, emailInput.Text);
My context:
public class DBCS : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<ShippingProfile> ShippingProfiles { get; set; }
public DbSet<Login> Logins { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>()
.HasRequired(user => user.ShippingProfiles)
.WithRequiredPrincipal();
}
}
So I am trying to add the user and I am getting the error
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int UserID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public Nullable<int> EmailList { get; set; }
public System.DateTime Birthday { get; set; }
public virtual Login Login { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<ShippingProfile> ShippingProfiles { get; set; }
public void AddUser(User user,string firstNameInput, string lastNameInput, int emailListInput, string bdayInput, string emailInput)
{
using (var dbContext = new DBCS())
{
user.Birthday = Convert.ToDateTime(bdayInput);
user.Email = emailInput;
user.EmailList = Convert.ToInt32(emailListInput);
user.FirstName = firstNameInput;
user.LastName = lastNameInput;
dbContext.Users.Add(user); // Error Here
dbContext.SaveChanges();
}
}
This can be a stupid question, but I would appreciate some help.
Thanks in advance!

Signature of AddUser have 5 parameters. When using this method you are passing 6 parameters.
Object reference error is coming from implementation of AddUser method, where 'user'' is not initialized and added into dbContext.Users.

Related

Entity Framework error while saving changes

I'm new to Entity Framework. At the moment I'm having a problem - when I try to insert a new User object into the database (using method RegisterNewUser), I keep getting an error:
Violation of PRIMARY KEY constraint 'PK__Users__3214EC07705D23AE'. Cannot insert duplicate key in object 'dbo.Users'. The duplicate key value is (0).
There are some similar questions here, but none of these answers have helped me.
public void RegisterNewUser(String uName, String uPass, String fName, String lName, String email)
{
User user = new User();
user.Username = uName;
user.Password = uPass;
user.FirstName = fName;
user.LastName = lName;
user.Email = email;
Time time = new Time();
time.Time1 = DateTime.Now;
user.Times.Add(time);
ur.AddUser(user);
}
Time and User objects:
public partial class Time
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public int UserId { get; set; }
public System.DateTime Time1 { get; set; }
public virtual User User { get; set; }
}
public partial class User
{
public User()
{
this.Times = new HashSet<Time>();
}
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public virtual ICollection<Time> Times { get; set; }
}
Repository file
public class UsersRepository
{
UsersDBContext userDBContext = new UsersDBContext();
public List<User> GetUsers()
{
return userDBContext.Users.Include("Times").ToList();
}
public void AddUser(User user)
{
userDBContext.Users.Add(user);
userDBContext.SaveChanges();
}
}
And context
public partial class UsersDBContext : DbContext
{
public UsersDBContext() : base("name=UsersDBContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<Time> Times { get; set; }
public virtual DbSet<User> Users { get; set; }
}
I have no idea how to solve this so any suggestions would be very helpful
set a value of Id field
or
define the Id field as autoincrement

Entity Framework Navigation Property Error

I am getting this error in my .Net MVC 4 web application:
The property 'Username' cannot be configured as a navigation property. The
property must be a valid entity type and the property should have a non-abstract
getter and setter. For collection properties the type must implement
ICollection<T> where T is a valid entity type.
I am very new to Entity Framework and I can't seem to get around this issue. Here is some code:
//DB Context
public class EFDbContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Role> Roles { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>().HasMany(u => u.Roles).WithMany(r => r.Users).Map(x => x.MapLeftKey("Username").MapRightKey("RoleName").ToTable("Users_Roles"));
}
}
//Entity Classes
public class User
{
[Key]
public string Username { get; set; }
public string Password { get; set; }
public string Email { get; set; }
public string Comment { get; set; }
public int Level { get; set; }
public string PasswordQuestion { get; set; }
public string PasswordAnswer { get; set; }
public bool IsApproved { get; set; }
public DateTime LastActivityDate { get; set; }
public DateTime LastLoginDate { get; set; }
public DateTime LastPasswordChangedDate { get; set; }
public DateTime CreationDate { get; set; }
public bool IsOnLine { get; set; }
public bool IsLockedOut { get; set; }
public DateTime LastLockedOutDate { get; set; }
public int FailedPasswordAttemptCount { get; set; }
public DateTime FailedPasswordAttemptWindowStart { get; set; }
public int FailedPasswordAnswerAttemptCount { get; set; }
public DateTime FailedPasswordAnswerAttemptWindowStart { get; set; }
[InverseProperty("RoleName")]
public virtual ICollection<Role> Roles { get; set; }
public override string ToString()
{
return this.Username;
}
}
public class Role
{
[Key]
public string RoleName { get; set; }
public int Level { get; set; }
[InverseProperty("Username")]
public virtual ICollection<User> Users { get; set; }
public override string ToString()
{
return this.RoleName;
}
}
//Repository
public class EFUsersRepository : IUsersRepository
{
private EFDbContext context = new EFDbContext();
public IQueryable<User> Users
{
get { return context.Users; }
}
public User GetUser(string username)
{
return context.Users.Find(username); //THIS IS WHERE THE CRASH OCCURS
}
}
//DB Setup
Table Users, Role and Users_Role. Users_Role is a simple linking table with [username, role] columns both of type varchar.
The database tables columns & types match the two classes above (User,Role).
I inherited this project which was unfinished but I can't get it to run successfully. Any help understanding what the issue is would be helpful. Thanks!
It might be that Entity Framework is updated. Easiest way will be to recreate the DataModel.
Even if the previous programmer did not use Entity Data Mode, you can at least copy the auto generated code such as EFDbContext, Users and Roles classes.
It turns out, after commenting out enough items all day long, the the following lines are what caused this error for me:
[InverseProperty("RoleName")] //In file User.cs (as shown above)
[InverseProperty("UserName")] //in file Role.cs (as shown above)
I am still learning Entity Framework and I don't know why this was the solution, but it stopped the error which I reported above.
I hope that this helps someone else and if anyone wants to help me understand what the issue was in detail, please feel free. I am eager to learn.

MVC4 Entity Framework 6 Model State Validation Issues

I'm working on an MVC4 with EF6 project, and have run into a slightly small but frustrating problem. I have a situation where I have the [Required] attribute set in my dbcontext, however, I do want to allow said property to be okay with empty strings.
I have tried what was suggested in this article, http://www.dzone.com/articles/ef-code-firstmvc, as well as putting [DisplayFormat(ConvertEmptyStringToNull = false)] on my context properties.
When I POST from my login page, the First Name, Last Name, Email, Phone properties are null, which is throwing the ModelState out of whack, even though I've set it to allow those properties to be empty strings. Am I missing something?
Model / DBContext
public class User : Entity
{
[StringLength(200)]
[DisplayFormat(ConvertEmptyStringToNull = false)]
[Required]
public String UserName { get; set; }
[StringLength(250)]
[DisplayFormat(ConvertEmptyStringToNull = false)]
[Required]
public String Password { get; set; }
[StringLength(200)]
[DisplayFormat(ConvertEmptyStringToNull = false)]
[Required]
public String FirstName { get; set; }
[StringLength(200)]
[DisplayFormat(ConvertEmptyStringToNull = false)]
[Required]
public String LastName { get; set; }
[StringLength(200)]
[DisplayFormat(ConvertEmptyStringToNull = false)]
[Required]
public String Email { get; set; }
[StringLength(200)]
[DisplayFormat(ConvertEmptyStringToNull = false)]
[Required]
public String Phone { get; set; }
}
Controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Login(UserViewModel Model)
{
var _UM = Model.User;
var User = _repo.GetSingle<User>(x => x.UserName == _UM.UserName);
if(User != null)
{
if (Hash.ValidatePassword(_UM.Password, User.Password))
{
return RedirectToAction("Dashboard");
}
else
{
ModelState.AddModelError("InvalidPass", "Invalid Credentials");
}
}
else
{
ModelState.AddModelError("NoUser", "Invalid Credentials");
}
return View(Model);
}
If invalid credentials are set, I would expect the ModelState keys to only have one of the items that I am explicity setting. However, it has 6 keys (First Name, Last Name, etc are required).
I ended up solving this by moving my EF context configurations to use the Fluent API instead of Data Annotations.
Model / DBContext
public class User : Entity
{
public String UserName { get; set; }
public String Password { get; set; }
public String FirstName { get; set; }
public String LastName { get; set; }
public String Email { get; set; }
public String Phone { get; set; }
}
DBContext File
public class DBContext : DbContext
{
public DBContext()
: base("ConString")
{
}
public DbSet<User> Users { get; set; }
public DbSet<UserRole> UserRoles { get; set; }
public DbSet<Region> Regions { get; set; }
public DbSet<InboundFile> InboundFiles { get; set; }
public DbSet<FileType> FileTypes { get; set; }
//configure objects
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>().Property(x => x.FirstName).IsRequired().HasMaxLength(200);
modelBuilder.Entity<User>().Property(x => x.LastName).IsRequired().HasMaxLength(200);
modelBuilder.Entity<User>().Property(x => x.Phone).IsRequired().HasMaxLength(200);
modelBuilder.Entity<User>().Property(x => x.Email).IsRequired().HasMaxLength(200);
modelBuilder.Entity<User>().Property(x => x.UserName).IsRequired().HasMaxLength(200);
modelBuilder.Entity<User>().Property(x => x.Password).IsRequired().HasMaxLength(200);
}
}

How to properly map entities using Fluent API?

I have two entities, a User and a UserProfile. The PK of User is UserId, the PK of UserProfile is UserProfileId. Every time a new user is created in my app, I create a new UserProfile whose PK is the same as the PK in User. When I then try to go update properties on the UserProfile I end up getting multiplicity errors or schema invalid errors. Here are my two entities:
public class User
{
public Guid UserId { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int? PhoneExtension { get; set; }
public string Comment { get; set; }
public Boolean IsApproved { get; set; }
public int PasswordFailuresSinceLastSuccess { get; set; }
public DateTime? LastPasswordFailureDate { get; set; }
public DateTime? LastActivityDate { get; set; }
public DateTime? LastLockoutDate { get; set; }
public DateTime? LastLoginDate { get; set; }
public string ConfirmationToken { get; set; }
public DateTime? CreateDate { get; set; }
public Boolean IsLockedOut { get; set; }
public DateTime? LastPasswordChangedDate { get; set; }
public string PasswordVerificationToken { get; set; }
public DateTime? PasswordVerificationTokenExpirationDate { get; set; }
public virtual ICollection<Role> Roles { get; set; }
public virtual UserProfile UserProfile { get; set; }
}
public class UserProfile
{
public Guid UserProfileId { get; set; }
public virtual User ProfileOwner { get; set; }
public Int64? HomePhone { get; set; }
public Int64? MobilePhone { get; set; }
public virtual User Manager { get; set; }
}
..and here are my only defined relationships using Fluent API.
modelBuilder.Entity<UserProfile>()
.HasKey(e => e.UserProfileId);
modelBuilder.Entity<UserProfile>()
.Property(e => e.UserProfileId)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
modelBuilder.Entity<UserProfile>()
.HasRequired(e => e.ProfileOwner)
.WithRequiredDependent(r => r.UserProfile);
Finally, my UserService creates a new user and at the same time creates a new UserProfile whose Guid UserProfileId is the same as the User's Guid UserId. Right after the user and profile are created, I try to update the manager in the UserProfile with my UserProfileService using this:
public void UpdateUserProfile(UserProfile updatedUserProfile)
{
UserProfile oldUserProfile = GetUserProfileByID(updatedUserProfile.UserProfileId);
oldUserProfile.Manager = updatedUserProfile.Manager;
oldUserProfile.HomePhone = updatedUserProfile.HomePhone;
oldUserProfile.MobilePhone = updatedUserProfile.MobilePhone;
this.SetEntityState(oldUserProfile, EntityState.Modified);
this.UnitOfWork.SaveChanges();
}
The this.SetEntityState line throws this error:
Multiplicity constraint violated. The role 'UserProfile_ProfileOwner_Source' of the relationship 'WhelenPortal.Data.Context.UserProfile_ProfileOwner' has multiplicity 1 or 0..1.
I've been trying to get this working for TWO DAYS now, PLEASE HELP!!! Thanks in advance.
As requested, here is some additional information. I'm using the repository pattern and unit of work here. My GetUserProfileById code is below. The service uses the repository so I show both.
public UserProfile GetUserProfileByID(Guid id)
{
if (id == null)
throw new BusinessServicesException(Resources.UnableToRetrieveUserProfileExceptionMessage, new ArgumentNullException("id"));
try
{
Model.UserProfile userProfile = _userProfileRepository.GetUserProfileByID(id);
if (userProfile != null)
return ToServicesUserProfile(userProfile);
return null;
}
catch (InvalidOperationException ex)
{
throw new BusinessServicesException(Resources.UnableToRetrieveUserProfileExceptionMessage, ex);
}
}
..and the repository:
public UserProfile GetUserProfileByID(Guid id)
{
return this.GetDbSet<UserProfile>().Find(id);
}
So after much playing around this is what ended up working for me, hopefully it can help someone else in some fashion. My User class stayed exactly the same but my UserProfile class changed to this:
public class UserProfile
{
public Guid UserProfileId { get; set; }
public virtual User ProfileOwner { get; set; }
public Guid? ManagerId { get; set; }
public virtual User Manager { get; set; }
public Int64? HomePhone { get; set; }
public Int64? MobilePhone { get; set; }
}
And here is the fluent mapping:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>()
.HasOptional(u => u.UserProfile)
.WithRequired(u => u.ProfileOwner);
modelBuilder.Entity<UserProfile>()
.HasOptional(u => u.Manager)
.WithMany()
.HasForeignKey(u => u.ManagerId);
}

Entity Framework 4.1 Code First Self-Referencing One-to-Many and Many-to-Many Associations

I have a User that can have collection of users he likes...
Another user can have collection of users he likes....
If User A likes User B and if User B likes User A, then they get to hang out. I need to send each other their contact info. How do we represent such a model in Entity Framework Code First?
public class User
{
public int UserId { get; set; }
public int? UserLikeId { get; set; }
public virtual UserLike UserLike { get; set; }
}
public class UserLike
{
public int UserLikeId { get; set; }
public int UserId { get; set; }
public virtual User User { get; set; }
public virtual ICollection<User> LikeUsers { get; set; }
}
Is this model correct? I can't get this to work.
I've tried another way but that doesn't work too...
I tried to add collection of user to user table.
For ex :
public virtual ICollection<User> userlike { get; set; }
public class User
{
public int UserId { get; set; }
public virtual ICollection<UserLike> UserLikes { get; set; }
}
public class UserLike
{
public int UserLikeId { get; set; }
public int UserId { get; set; }
public virtual User User { get; set; }
public int LikeUserId { get; set; }
public virtual User LikeUser { get; set; }
}
I get this error when I try to add user and who they like:
Conflicting changes to the role 'UserLike_LikeUser_Target' of the relationship 'UserLike_LikeUser' have been detected.
What's the best way to represent such a model?
You don't really need a separate entity to describe the relationship, the object model below will do the trick:
public class User
{
public int UserId { get; set; }
public string Name { get; set; }
public int? ThisUserLikesId { get; set; }
public virtual User ThisUserLikes { get; set; }
public virtual ICollection<User> LikeThisUser { get; set; }
}
public class Context : DbContext
{
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>()
.HasOptional(u => u.ThisUserLikes)
.WithMany(u => u.LikeThisUser)
.HasForeignKey(u => u.ThisUserLikesId);
}
}
Now let's say you have a UserId in your hand and want to find the other User who likes this user which this user also like him:
using (var context = new Context())
{
// For a given user id = 1
var friends = (from u in context.Users
where u.UserId == 1
from v in u.LikeThisUser
where v.UserId == u.ThisUserLikesId
select new
{
OurUser = u,
HerFriend = v
})
.SingleOrDefault();
ExchangeContactInfo(friends.OurUser, friends.HerFriend);
}
Update 1:
A self referencing many-to-many association will be mapped to database using a join table which require a different object model and fluent API altogether:
public class User
{
public int UserId { get; set; }
public string Name { get; set; }
public virtual ICollection<User> ThisUserLikes { get; set; }
public virtual ICollection<User> UsersLikeThisUser { get; set; }
}
public class Context : DbContext
{
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>()
.HasMany(u => u.ThisUserLikes)
.WithMany(u => u.UsersLikeThisUser)
.Map(c =>
{
c.MapLeftKey("UserId");
c.MapRightKey("OtherUserId");
c.ToTable("UserLikes");
});
}
}
Update 2:
As I explained in this post, a many-to-many association cannot have a payload (e.g EventId), and if that’s the case then we have to break it down to two one-to-many associations to an intervening class and I can see you’ve correctly created this class (UserLike) to represent the extra information attached to your self-referencing many-to-many association but the associations from this intermediate class are not correct as we need to define exactly 2 many-to-one association from UserLike to User like I showed in the following object model:
public class User
{
public int UserId { get; set; }
public string Email { get; set; }
public virtual ICollection ThisUserLikes { get; set; }
public virtual ICollection UsersLikeThisUser { get; set; }
}
public class UserLike
{
public int UserLikeId { get; set; }
public int LikerId { get; set; }
public int LikeeId { get; set; }
public int EventId { get; set; }
public User Liker { get; set; }
public User Likee { get; set; }
public virtual Event Event { get; set; }
}
public class Event
{
public int EventId { get; set; }
public string Name { get; set; }
}
public class Context : DbContext
{
public DbSet Users { get; set; }
public DbSet Events { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity()
.HasMany(u => u.ThisUserLikes)
.WithRequired(ul => ul.Liker)
.HasForeignKey(ul => ul.LikerId);
modelBuilder.Entity()
.HasMany(u => u.UsersLikeThisUser)
.WithRequired(ul => ul.Likee)
.HasForeignKey(ul => ul.LikeeId)
.WillCascadeOnDelete(false);
}
}
Now you can use the following LINQ query to retrieve all the users who like each other:
using (var context = new Context())
{
var friends = (from u1 in context.Users
from likers in u1.UsersLikeThisUser
from u2 in u1.ThisUserLikes
where u2.LikeeId == likers.LikerId
select new
{
OurUser = u1.UserId,
HerFriend = u2.LikeeId
})
.ToList();
}
Hope this helps.