I'm using asp.net default membership provider to create a website.
I used 'EF Reverse POCO Generator' and got some csharp code of build-in membership tables, I removed some classes and kept only Applications, Memberships, Profiles, Roles and Users.
The problem is I cannot use them because of exceptions throwing when the database is initialized.
The first exception I encountered is complaining missing the primary key, I added [Key] annotation to the primary field, problem solved.
Then I got the second error seems complaining missing foreign keys:
Unable to determine the principal end of an association between the types 'GoHome.Models.Memberships' and 'GoHome.Models.Users'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.
Looks like can be solved by adding [ForeignKey], but after that I still got the third one, which I cannot find a solution in Google:
*Introducing FOREIGN KEY constraint 'FK_dbo.RolesUsers_dbo.Users_Users_UserId' on table 'RolesUsers' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.*
Quite odd, as looks to me there is no table called 'RolesUsers' at all.
I only added two [ForeignKey] in Memberships and Profiles respectively, which resulted in the third error. Here is the code:
// Memberships
public class Memberships
{
//[ForeignKey("Applications")]
public Guid ApplicationId { get; set; } // ApplicationId
[Key]
[ForeignKey("Users")]
public Guid UserId { get; set; } // UserId (Primary key)
public string Password { get; set; } // Password
public int PasswordFormat { get; set; } // PasswordFormat
public string PasswordSalt { get; set; } // PasswordSalt
public string Email { get; set; } // Email
public string PasswordQuestion { get; set; } // PasswordQuestion
public string PasswordAnswer { get; set; } // PasswordAnswer
public bool IsApproved { get; set; } // IsApproved
public bool IsLockedOut { get; set; } // IsLockedOut
public DateTime CreateDate { get; set; } // CreateDate
public DateTime LastLoginDate { get; set; } // LastLoginDate
public DateTime LastPasswordChangedDate { get; set; } // LastPasswordChangedDate
public DateTime LastLockoutDate { get; set; } // LastLockoutDate
public int FailedPasswordAttemptCount { get; set; } // FailedPasswordAttemptCount
public DateTime FailedPasswordAttemptWindowStart { get; set; } // FailedPasswordAttemptWindowStart
public int FailedPasswordAnswerAttemptCount { get; set; } // FailedPasswordAnswerAttemptCount
public DateTime FailedPasswordAnswerAttemptWindowsStart { get; set; } // FailedPasswordAnswerAttemptWindowsStart
public string Comment { get; set; } // Comment
// Foreign keys
public virtual Applications Applications { get; set; } // MembershipApplication
public virtual Users Users { get; set; } // MembershipUser
}
// Profiles
public class Profiles
{
[Key]
[ForeignKey("Users")]
public Guid UserId { get; set; } // UserId (Primary key)
public string PropertyNames { get; set; } // PropertyNames
public string PropertyValueStrings { get; set; } // PropertyValueStrings
public byte[] PropertyValueBinary { get; set; } // PropertyValueBinary
public DateTime LastUpdatedDate { get; set; } // LastUpdatedDate
// Foreign keys
public virtual Users Users { get; set; } // UserProfile
}
Related
I'm trying xamarin app... and I needed sqlite database... that contain 3 tables... users, accounts and transactions... the table of account seems:
[Table(nameof(Account))]
class Account
{
[PrimaryKey,AutoIncrement]
public int Id { get; set; }
public string Name { get; set; }
[ForeignKey(typeof(User))]
public int UserId { get; set; }
public double Balance { get; set; }
[ManyToOne]
public User User { get; set; }
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<Transaction> Transactions { get; set; }
}
I think there is no problem until here...
but in transaction table there are tow columns, FirstAccountId and TargetAccountId,so I like that:
[Table(nameof(Transaction))]
class Transaction
{
[PrimaryKey,AutoIncrement]
public int Id { get; set; }
[ForeignKey(typeof(Account))]
public int TargetAccountId { set; get; }
[ForeignKey(typeof(Account))]
public int FirstAccountId { get; set; }
public DateTime DateOfTransaction { get; set; }
[ManyToOne()]
public Account Account1 { get; set; }
[ManyToOne()]
public Account Account2 { get; set; }`
}
How I can make Account1 is the account for FirstAccountId and Account2 is the account for TargetAccountId
According to the source code of ManyToOne (see here), it takes an string foreignKey as a parameter. I did not find anything about it in the documentation, but I'd assume that you can specify an foreign key explicitly using this parameter, although I did not find anything about it in the documentation
[ManyToOne(nameof(FirstAccountId))]
public Account Account1 { get; set; }
[ManyToOne(nameof(TargetAccountId))]
public Account Account2 { get; set; }
I have got several models:
Course.cs
public class Course
{
public Guid Id { get; set; }
public ICollection<ApplicationUser> Teacher { get; set; }
public string Name { get; set; }
public string ShortName { get; set; }
public DateTime CreationDate { get; set; }
public bool IsActive { get; set; }
}
Group.cs
public class Group
{
public Guid Id { get; set; }
public ApplicationUser Mentor { get; set;}
public string DisplayName { get; set; }
public string GroupName { get; set; }
public DateTime StartYear { get; set; }
public string InviteCode { get; set; }
public ICollection<ApplicationUser> Students { get; set; }
public ICollection<Course> Courses { get; set; }
}
ApplicationUser.cs
public class ApplicationUser : IdentityUser
{
[Required]
public string Firstname { get; set; }
[Required]
public string Surname { get; set; }
public bool Gender { get; set; }
public DateTime Birthdate { get; set; }
//[Required]
public string InviteCode { get; set; }
public Guid GroupId { get; set; }
[ForeignKey("GroupId")]
public Group CurrentGroup { get; set; }
public ICollection<Group> PastGroups { get; set; }
}
Now when I try to register (using Identity) a user (not even trying to give the user a group) I receive this error:
SqlException: The INSERT statement conflicted with the FOREIGN KEY
constraint "FK_AspNetUsers_Groups_GroupId". The conflict occurred in
database "aspnet-Project_Dojo-3af15f80-8c62-40a6-9850-ee7a296d0726",
table "dbo.Groups", column 'Id'. The statement has been terminated.
In my modelBuilder I have added some logics for the relations between Group, ApplicationUser (Students) and the Foreign Key:
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// Customize the ASP.NET Identity model and override the defaults if needed.
// For example, you can rename the ASP.NET Identity table names and more.
// Add your customizations after calling base.OnModelCreating(builder);\\
builder.Entity<ApplicationUser>()
.HasOne(p => p.CurrentGroup)
.WithMany(b => b.Students)
.HasForeignKey(p => p.GroupId);
}
I don't know what this is exactly doing, but I've been browsing some Stackoverflow threads to come to this code (migrations weren't working without it).
I look forward to a solution for my problem. Once again, I'm not doing ANYTHING with the groups yet when registering.
Thanks in advance!
not even trying to give the user a group
Well there's your problem, it's required.
Either provide a group, or make it optional by making the foreign key nullable (Guid? GroupId).
Because it's currently a non-nullable struct, it'll have a default value of all zeroes (Guid.Empty). This FK is not known in your database, resulting in the error you see.
I have a class Ticket which has some properties. Three of these (View, Task and Key) properties are navigation properties. Those properties already exist in database even before a ticket has been stored. In my application I load those properties from the database first and then create a Ticket object. I need to save only the ticket (not the underlying objects ) to the database with the id to Key, View and Task (these are primery keys in the Ticket table)
[Table("Tickets")]
public class Ticket
{
[Key]
public int Id { get; set; }
public DateTime? Created { get; set; }
[Required]
public View View{ get; set; }
[Required]
public Key Key { get; set; }
public Task Task { get; set; }
}
I try to save the Ticket object like this:
db.Tickets.Add(ticket);
db.Entry(ticket.Key).State = System.Data.Entity.EntityState.Unchanged;
db.Entry(ticket.View).State = System.Data.Entity.EntityState.Unchanged;
db.Entry(ticket.Task).State = System.Data.Entity.EntityState.Unchanged;
db.SaveChanges();
When I try this approach I get the error:
{"Message":"An error has occurred.","ExceptionMessage":"Saving or accepting changes failed because more than one entity of type 'Key' have the same primary key value. Ensure that explicitly set primary key values are unique. Ensure that database-generated primary keys are configured correctly in the database and in the Entity Framework model. Use the Entity Designer for Database First/Model First configuration. Use the 'HasDatabaseGeneratedOption\" fluent API or 'DatabaseGeneratedAttribute' for Code First configuration.","
Is it even possible to work with Entity Framework this way? Having pre defined data which is loaded to it's objects (Key, View, Task) first and later assign these objects to an object having these properties but then in the entity framework context only adding the parent object, in this case the ticket?
I have also tried to set the underlying objects to null but then I will loose the data for those underlying objects, data I need later on in the application.
This is how the underlying objects look like:
[Table("Views")]
public class View
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Version { get; set; }
[Required]
public DateTime? Created { get; set; }
}
[Table("Keys")]
public class Key
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Version { get; set; }
[Required]
public DateTime? Created { get; set; }
}
[Table("Tasks")]
public class Task
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Version { get; set; }
[Required]
public DateTime? Created { get; set; }
}
Try adding Foreign Keys to your object and making those required instead of making the navigation property required. Like so:
[Table("Tickets")]
public class Ticket
{
[Key]
public int Id { get; set; }
public DateTime? Created { get; set; }
[Required]
public int ViewId {get; set; }
[ForeignKey("ViewId")]
public View View{ get; set; }
[Required]
public int KeyId {get; set; }
[ForeignKey("KeyId")]
public Key Key { get; set; }
public Task Task { get; set; }
}
Is it possible to add fields/columns to webpages_Membership?
[Table("webpages_Membership")]
public class Membership
{
public Membership()
{
Roles = new List<Role>();
OAuthMemberships = new List<OAuthMembership>();
}
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public int UserId { get; set; }
public DateTime? CreateDate { get; set; }
[StringLength(128)]
public string ConfirmationToken { get; set; }
public bool? IsConfirmed { get; set; }
public DateTime? LastPasswordFailureDate { get; set; }
public int PasswordFailuresSinceLastSuccess { get; set; }
[Required, StringLength(128)]
public string Password { get; set; }
public DateTime? PasswordChangedDate { get; set; }
[Required, StringLength(128)]
public string PasswordSalt { get; set; }
[StringLength(128)]
public string PasswordVerificationToken { get; set; }
public DateTime? PasswordVerificationTokenExpirationDate { get; set; }
public ICollection<Role> Roles { get; set; }
[ForeignKey("UserId")]
public ICollection<OAuthMembership> OAuthMemberships { get; set; }
}
I want to add LogonCount as a field/column, but this table gets filled automatically by the membership provider upon creating a CreateUserAndAccount().
I don't seem to have any influence on giving the LogonCount a value at CreateUserAndAccount().
The standard way to add information relevant to a given userId is in the UserProfile table, not the webpages_Membership table. See my answer here and Jon Galloway's post on "SimpleMembership, Membership Providers, Universal Providers and the new ASP.NET 4.5 Web Forms and ASP.NET MVC 4 templates" for more info about how SimpleMembership ties together with UserProfile.
I don't seem to have any influence on giving the LogonCount a value ...
You then access the UserProfile table and information through your database context, not through the membership provider, which is really there to give you access to a core set of features only.
using (MyDbContext db = new MyDbContext())
{
UserProfile user = db.UserProfiles
.First(u => u.UserName.ToLower() == model.UserName.ToLower());
user.LogonCount = 1;
db.SaveChanges();
}
I have two model class, where I want to make one-to-one relation. When I make migration, I get an error:
The ALTER TABLE statement conflicted with the FOREIGN KEY constraint
"FK_dbo.Uzytkownik_dbo.UserProfile_UserId". The conflict occurred in
database "db_wydarzenia", table "dbo.UserProfile", column 'UserId'.
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
}
[Table("Uzytkownik")]
public class Uzytkownik
{
[Key]
public int UzytkownikID { get; set; }
public int UserId { get; set; }
public string Imie { get; set; }
public string Nazwisko { get; set; }
public string Telefon { get; set; }
public string Email { get; set; }
[ForeignKey("UserId")]
public UserProfile UserProfile { get; set; }
}
EDIT:
Problem solved :)
I remove all data from uzytkownik table and it's go.
If you want one-to-one - you cannot have both the primary-key and the foreign-key specified. One-to-one is modeled via primary-keys (pk == pk), otherwise it becomes 'multiplicity' (and just typical one-to-many).
To get what you want just remove your other PK - and user UserId as both primary and fk...
[Table("Uzytkownik")]
public class Uzytkownik
{
// [Key] public int UzytkownikID { get; set; }
[Key]
public int UserId { get; set; }
[ForeignKey("UserId")]
public UserProfile UserProfile { get; set; }
}