Cannot insert the value NULL into column 'RoleId' (mvc4 simple membership) - asp.net-mvc-4

I noticed that someone else has faced the same problem such as Cannot insert the value NULL into column 'UserId' but it should be caused by different reasons.
The problem can be simplified like this:
UsersContext _usersContext = new UsersContext();
...
var usersInRole = new UsersInRole() { RoleId = 3, UserId = 1 };
_usersContext.UsersInRoles.Add(usersInRole);
_usersContext.SaveChanges();
The last line of code threw an exception
"An error occurred while updating the entries. See the inner exception
for details."
, and the InnerException was saying the same thing
"An error occurred while updating the entries. See the inner exception
for details."!
Fortunately, the InnerException of the InnerException says
"Cannot insert the value NULL into column 'RoleId', table
'MFC.dbo.webpages_UsersInRoles'; column does not allow nulls. INSERT
fails.\r\nThe statement has been terminated."
. which means "RoleId = 3" was modified or ignored, how could that happen?
Some other code might help are listed below:
[Table("webpages_UsersInRoles")]
public partial class UsersInRole
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int RoleId { get; set; }
public int UserId { get; set; }
}
public class UsersContext : DbContext
{
public UsersContext()
: base("MFCConnectionString")
{
}
public DbSet<UsersInRole> UsersInRoles { get; set; }
}
and table creation scripts:
CREATE TABLE [dbo].[webpages_UsersInRoles] (
[UserId] INT NOT NULL,
[RoleId] INT NOT NULL,
PRIMARY KEY CLUSTERED ([UserId] ASC, [RoleId] ASC),
CONSTRAINT [fk_UsersInRoels_RoleId] FOREIGN KEY ([RoleId]) REFERENCES [dbo].[webpages_Roles] ([RoleId]),
CONSTRAINT [fk_UsersInRoles_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[UserProfile] ([UserId])
);
Another thing intersting is that I can remove an usersInRole from the context, namely, the following code is ok (if I added the record manually):
UsersContext _usersContext = new UsersContext();
...
var usersInRole = _usersContext.UsersInRoles.SingleOrDefault(i => i.RoleId == 3 && UserId == 1);
_usersContext.UsersInRoles.Remove(usersInRole);
_usersContext.SaveChanges();
Seems few people are using and talking simple membership, thus I havevn't found many helpful resource from Google. So any help will be appreciated. Thanks.
Here is the solution:
As Tommy said, this problem is caused by the [Key] attributes.
Rather than deleting the [Key](which will cause an error like "entity type has no key defined"), I changed the code to offical solution:
foreach (var role in roles)
{
foreach (var user in UserProfile.GetAllUserProfiles(_usersContext))
{
var usersInRole = _usersContext.UsersInRoles.SingleOrDefault(uio => uio.RoleId == role.RoleId && uio.UserId == user.UserId);
var key = user.UserId + "_" + role.RoleId;
if (collection.AllKeys.Any(i => i == key) && collection[key].Contains("true") && usersInRole == null)
{
Roles.AddUserToRole(user.UserName, role.RoleName); //Key codes!
}
if (collection.AllKeys.Any(i => i == key) && !collection[key].Contains("true") && usersInRole != null)
{
Roles.RemoveUserFromRole(user.UserName, role.RoleName); //Key codes!
}
}
}
Seems that Roles.AddUserToRole and Roles.RemoveUserFromRole can do it correctly.
But it's not finished yet..... Strangely, _userContext.UsersInRoles cannot return correct results. For example, if the data in table is:
RoleId UserId
5 1
5 2
5 3
it returns 3 records (5,1)(5,1)(5,1) rather than (5, 1)(5, 2)(5, 3). This is the thing Tommy mentioned in his reply but bypassed by Roles.Add/Remove(). The solution is:
1. Add a [ID] column to the table:
CREATE TABLE [dbo].[webpages_UsersInRoles] (
[ID] INT NOT NULL IDENTITY, --Key codes!
[UserId] INT NOT NULL,
[RoleId] INT NOT NULL,
PRIMARY KEY CLUSTERED ([UserId] ASC, [RoleId] ASC),
CONSTRAINT [fk_UsersInRoels_RoleId] FOREIGN KEY ([RoleId]) REFERENCES [dbo].[webpages_Roles] ([RoleId]),
CONSTRAINT [fk_UsersInRoles_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[UserProfile] ([UserId])
);
2. Add the new column to the entity RIGHT UNDER THE [KEY]:
[Table("webpages_UsersInRoles")]
public partial class UsersInRole
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int ID { get; set; } //Key codes!
public int RoleId { get; set; }
public int UserId { get; set; }
}
Now I get (5, 1)(5, 2)(5, 3)!
I know little about database, but as Tommy mentioned, this should be caused by declaring RoleId under [Key][Database....] with PRIMARY KEY CLUSTERED ([UserId] ASC, [RoleId] ASC) in scripts together.

I think your problem is with the following section
public partial class UsersInRole
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int RoleId { get; set; }
public int UserId { get; set; }
}
Having the Key and DatabaseGeneratedAttribute is telling EF that the database is going to assign the value (IDENTITY column). However, your database is not auto assigning this value. So, when EF is trying to do the insert, it is ignoring your RoleId that you assigned because it thinks the database is going to auto assign it. Remove those two attributes on the RoleId property and see if you continue to have the same issues.

1) Why are you using DbContext to add Roles to user? There are some native Membership methods to do it:
Roles.AddUsersToRole(string[] usernames, string rolename)
Roles.AddUserToRole(string username, string rolename) //**This one fits your purpose
Roles.AddUserToRoles(string username, string[] rolenames)
...
2) Value in key column can't be null
3) Int can't be null in C#. If you want to set null value to int, you should define it as nullable: int?

Related

RawSQL and auto-generated keys in EF Core 3.1

I have a Model with a Guid primary key. I want the Database to generate a key on insert so I added the following annotations:
public class Employee
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid employee_id { get; set; }
[Required]
public int employee_number { get; set; }
//more props...
}
Now I expected that inserts with RawSQL wouldn't expect a primary key, however the folllowing statement doesn't work when executred through ExecuteSqlRaw:
INSERT INTO employees (employee_number/**, more props*/)
VALUES (123 /**,more props*/)
An error is caused by the DB about a non-nullable primary key. Explicitly inserting some random Guid works, but i figured the DB would take care of this.
Is the Identity annotation wrong?
You could miss one step.
When I add migration, ef core will generate a migration file. Then defaultValueSql: "newsequentialid()" need to be added here.
After excuting Update-Database, I can insert the record with RawSQL.
Edit:
Another method to use HasDefaultValueSql in DbContext.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Employee>()
.Property(b => b.employee_id)
.HasDefaultValueSql("newsequentialid()");
}

Mapping-By-Code ignores Column Name in BagPropertyMapper

I'm encountering a problem, and I think it's an NHibernate defect.
My Database Schema, containing a simple Parent-Child mapping:
TABLE Company
(
ID BIGINT PRIMARY KEY
)
TABLE CompanyMailRecipient
(
ID BIGINT PRIMARY KEY IDENTITY(1, 1),
Company_ID BIGINT NOT NULL FOREIGN KEY REFERENCES Company(id),
Name VARCHAR(MAX),
EmailAddress VARCHAR(MAX),
DestinationType TINYINT
)
My classes. Note that the CompanyMailRecipient table has a column called EmailAddress, but my MailRecipient class has a column called Address.
public enum MessageDestinationType
{
Normal = 1,
CC = 2,
BCC = 3
}
public class MailRecipient
{
public virtual string Name {get; set }
public virtual string Address {get; set; } // Different name to the column!
public virtual MessageDestinationType DestinationType {get; set;}
}
public class MailConfiguration
{
private Lazy<IList<MailRecipient>> _recipients = new Lazy<IList<MailRecipient>>(() => new List<MailRecipient>());
public virtual IList<MailRecipient> Recipients
{
get
{
return _recipients.Value;
}
set
{
_recipients = new Lazy<IList<MailRecipient>>(() => value);
}
}
}
public class Company
{
public virtual long Id { get; set; }
public virtual MailConfiguration MailConfiguration { get; set; }
}
The mapping code
mapper.Class<Company>(
classMapper =>
{
classMapper.Table("Company");
classMapper.Component(
company => company.MailConfiguration,
componentMapper =>
{
componentMapper.Bag(mc => mc.Recipients,
bagPropertyMapper =>
{
bagPropertyMapper.Table("CompanyMailRecipient");
bagPropertyMapper.Key(mrKeyMapper =>
{
mrKeyMapper.Column("Company_Id");
});
},
r => r.Component(
mrc =>
{
mrc.Property
(
mr => mr.Name,
mrpm => mrpm.Column("Name")
);
/*****************************/
/* Here's the important bit */
/*****************************/
mrc.Property
(
mr => mr.Address,
mrpm => mrpm.Column("EmailAddress");
);
mrc.Property
(
mr => mr.DestinationType,
mrpm => mrpm.Column("DestinationType")
);
};
)
);
}
}
Now here's the problem: when I attempt to query a Company, I get the following error (with significant parts in bold)
NHibernate.Exceptions.GenericADOException : could not initialize a collection: [Kiosk.Server.Entities.Company.MailConfiguration.Recipients#576][SQL: SELECT recipients0_.Company_Id as Company1_0_, recipients0_.Name as Name0_, recipients0_.Address as Address0_, recipients0_.DestinationType as Destinat4_0_ FROM CompanyMailRecipient recipients0_ WHERE recipients0_.Company_Id=?]
----> System.Data.SqlClient.SqlException : Invalid column name 'Address'.
at NHibernate.Loader.Loader.LoadCollection(ISessionImplementor session, Object id, IType type)
But, if I change my C# code so my MailRecipient class has a propery called EmailAddress instead of Address, everything works.
It's like NHibernate is ignoring my column mapping.
Is this an NHibernate bug, or am I missing something?
The version of NHibernate I'm using is 4.0.4.4.
The example above has a one-to-many component hanging off a component that hangs off the entity.
I found that if I removed a layer of inderection, and had my one-to-many component hanging off the entity directly, then the column name takes effect.
Yes, this was indeed a bug in NHibernate.
I issued a fix as a pull request which has now been merged into the codebase. It should be in a release after 4.1.1.
Bug NH-3913
GitHub Commit

How to add a foreign key column to AspNetUserRoles table Owin Authentication

I am currently working on a MVC 5 project where I have created a new table (code first) AspNetApplications (column1 ApplicationId, column2 ApplicationName).
I want to extend the AspNetUserRoles table where I want to add ApplicationId as a foreign key column.
Could please anyone tell me how I can achieve this in code first approach?
Above to my question, I have successfully added the ApplicationId as a foreign key column in AspNetUserRoles table as follow
public class AspNetUserRoles : IdentityUserRole
{
[Key]
public string ApplicationId { get; set; }
[ForeignKey("ApplicationId")]
public AspNetApplications AspNetApplications { get; set; }
}
Now I can see ApplicationId column in the table but a weird thing happened where it has added a Discriminator column to the AspNetUserRoles table. Can please someone tell me what I have done wrong here. Following is my migration script
public partial class AspNetUserRolesApplicationId : DbMigration
{
public override void Up()
{
AddColumn("dbo.AspNetUserRoles", "ApplicationId", c => c.String(maxLength: 128));
AddColumn("dbo.AspNetUserRoles", "Discriminator", c => c.String(nullable: false, maxLength: 128));
CreateIndex("dbo.AspNetUserRoles", "ApplicationId");
AddForeignKey("dbo.AspNetUserRoles", "ApplicationId", "dbo.AspNetApplications", "ApplicationId");
}
public override void Down()
{
DropForeignKey("dbo.AspNetUserRoles", "ApplicationId", "dbo.AspNetApplications");
DropIndex("dbo.AspNetUserRoles", new[] { "ApplicationId" });
DropColumn("dbo.AspNetUserRoles", "Discriminator");
DropColumn("dbo.AspNetUserRoles", "ApplicationId");
}
}

How to Customize index using code first? [duplicate]

Is there any way to implement the Guid COMB identity strategy for objects in the new Entity Framework 4.1 using the CodeFirst design? I thought setting the StoreGeneratedPattern would work, but it still gives me normal GUIDs.
Why worry about defaults for Guid columns in the database at all? Why not just generate the Guid on the client like any other value. That requires you have a method in your client code that will generate COMB-like guids:
public static Guid NewGuid()
{
var guidBinary = new byte[16];
Array.Copy( Guid.NewGuid().ToByteArray(), 0, guidBinary, 0, 8 );
Array.Copy( BitConverter.GetBytes( DateTime.Now.Ticks ), 0, guidBinary, 8, 8 );
return new Guid( guidBinary );
}
One of the advantages of the Guid is specifically that you can generate them on the client without a round trip to the database.
I guess you are using SQL server as your database. This is nice example of inconsistency among different MS tools. SQL server team doesn't recommend using newid() as default value for UNIQUEIDENTIFIER columns and ADO.NET team use it if you specify Guid property as autogenerated in the database. They should use newsequentialid() instead!
If you want sequential Guids generated by database you must modify generated table and it is really complex because you must find autogenerated default constraint, drop it and create new constraint. This all can be done in custom database initializer. Here you have my sample code:
class Program
{
static void Main(string[] args)
{
Database.SetInitializer(new CustomInitializer());
using (var context = new Context())
{
context.TestEntities.Add(new TestEntity() { Name = "A" });
context.TestEntities.Add(new TestEntity() { Name = "B" });
context.SaveChanges();
}
}
}
public class CustomInitializer : DropCreateDatabaseAlways<Context>
{
protected override void Seed(Context context)
{
base.Seed(context);
context.Database.ExecuteSqlCommand(#"
DECLARE #Name VARCHAR(100)
SELECT #Name = O.Name FROM sys.objects AS O
INNER JOIN sys.tables AS T ON O.parent_object_id = T.object_id
WHERE O.type_desc LIKE 'DEFAULT_CONSTRAINT'
AND O.Name LIKE 'DF__TestEntities__Id__%'
AND T.Name = 'TestEntities'
DECLARE #Sql NVARCHAR(2000) = 'ALTER TABLE TestEntities DROP Constraint ' + #Name
EXEC sp_executesql #Sql
ALTER TABLE TestEntities
ADD CONSTRAINT IdDef DEFAULT NEWSEQUENTIALID() FOR Id");
}
}
public class TestEntity
{
public Guid Id { get; set; }
public string Name { get; set; }
}
public class Context : DbContext
{
public DbSet<TestEntity> TestEntities { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<TestEntity>()
.Property(e => e.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
}
}
The simplest answer
public class User
{
public User(Guid? id = null, DateTime? created = null)
{
if (id != null)
Id = id;
if (created != null)
Created = created;
}
public User()
{
}
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public DateTime? Created { get; internal set; }
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid? Id { get; internal set; }
}
This assumes you have your database table set with the default of newsequentialid() which in my case is managed by FluentMigrator migrations.
if you use SQL Server, when a GUID property is configured as value generated on add, the provider automatically performs value generation client-side, using an algorithm to generate optimal sequential GUID values. refer to for more.
https://learn.microsoft.com/en-us/ef/core/modeling/generated-properties?tabs=fluent-api

At a loss, how to map two classes in Nhibernate

Please forgive the clumsy question (if you can figure out a better way to word the question feel free to edit away).
I have two classes SupportTicketCategory and SupportTicket (respectively):
public class SupportTicketCategory
{
public SupportTicketCategory()
{ }
private int _supportTicketCategoryID;
public virtual int SupportTicketCategoryID
{
get { return _supportTicketCategoryID; }
set
{
_supportTicketCategoryID = value;
}
}
private string _supportTicketCategoryName;
public virtual string SupportTicketCategoryName
{
get { return _supportTicketCategoryName; }
set
{
_supportTicketCategoryName = value;
}
}
}
and
public SupportTicket()
{ }
private int _supportTicketID;
public virtual int SupportTicketID
{
get { return _supportTicketID; }
set
{
_supportTicketID = value;
}
}
private SupportTicketCategory _supportTicketCategory;
public virtual SupportTicketCategory SupportTicketCategory { get; set; }
My table structure is as follows:
CREATE TABLE [dbo].[supporttickets](
[supportticketid] [int] IDENTITY(1,1) NOT NULL,
[supportticketcategoryid] [int] NOT NULL,
CONSTRAINT [PK_supporttickets] PRIMARY KEY CLUSTERED
(
[supportticketid] ASC
)
) ON [PRIMARY]
ALTER TABLE [dbo].[supporttickets]
WITH CHECK ADD CONSTRAINT
[FK_supporttickets_supportticketcategories]
FOREIGN KEY([supportticketcategoryid])
REFERENCES [dbo].[supportticketcategories] ([supportticketcategoryid])
ALTER TABLE [dbo].[supporttickets] CHECK CONSTRAINT [FK_supporttickets_supportticketcategories]
CREATE TABLE [dbo].[supportticketcategories](
[supportticketcategoryid] [int] IDENTITY(1,1) NOT NULL,
[supportticketcategoryname] [varchar](50) NOT NULL,
CONSTRAINT [PK_supportticketcategories] PRIMARY KEY CLUSTERED
(
[supportticketcategoryid] ASC
)
) ON [PRIMARY]
So basically, I want to map a SupportTicketCategory onto the SupportTicket like it is in my class, however I cannot figure out what is the proper mapping type and cannot find an example of this on the interwebs.
Update:
I changed the SupportTicketCategory property to old school getters and setters and it worked...syntax sugar for loss.
If you use MyGeneration with the NHibernate template, you can point it at your database and it will make the mappings for you, so you can see how it ought to be done.
I think what you're looking for is the "many-to-one" element. (This goes inside your class element for SupportTicket)
<many-to-one name="SupportTicketCategory" column="SupportTicketCategoryId" update="false" insert="false" />
Many to one mappings can be done like this:
<many-to-one name="SupportTicketCategory" class="SupportTicketCategory" not-null="false" column="SupportTicketCategoryId" />