I have a complex primary key in this table defined as follows
[Key, Column(Order = 1), DatabaseGenerated(DatabaseGeneratedOption.None)]
public int SymbolId { get; set; }
[Key, Column(Order = 2)]
public SymbolType SymbolType { get; set; }
[Key, Column(Order = 3), DataType(DataType.Date)]
public DateTime Date { get; set; }
I can add data to the table, the problem is I'm testing by adding data for the same SymbolId each time and not only is that SymbolId not what is showing up in the column, it appears to be an auto-increment column when I specified it to be of type DatabaseGeneratedOption.None. The actual SymbolId is 10 and that is what should be in the SymbolId column for each entry.
Here is what the table looks like in SQL Azure
If someone could enlighten me on where my problem lies it would be most appreciated.
Tried to reproduce it on azure but could not.
Things are working for me with the similar set of schema, here is my schema and data
You have problem in the database design.
There is no point to make one of the composite keys as Auto Increament.
Composite keys should not be Auto Increament.
Related
We've migrated away from using an incrementing ID column on the User table to generating the IDs in the Resource table and then a foreign key relationship to it.
We use the Code-First EF approach to generate migration scripts and the subsequent DB schema. At the moment we're trying to create a foreign key relationship between User Invite and User on the ResourceId. Not matter which way I try this, it ends up with EF creating a shadow foreign key property called ResourceId1 on the User table.
The foreign key property 'User.ResourceId1' was created in shadow state because a conflicting property with the simple name 'ResourceId' exists in the entity type, but is either not mapped, is already used for another relationship, or is incompatible with the associated primary key type.
You can create this kind of foreign key relationship inside SSMS without issue, but I can't find a way to do it via code-first.
Definitions
public class Resource
{
public int Id { get; set; }
}
public class User
{
public int Id { get; set; }
public int ResourceId { get; set; }
public Resource Resource { get; set; } = null!;
}
public class UserInvite
{
public int Id { get; set; }
public int? UserResourceId { get; set; }
[ForeignKey("UserResourceId")]
public User? User { get; set; }
}
Fluent API
Tried the following (separately)
modelBuilder.Entity<UserInvite>()
.HasOne(ui => ui.User)
.WithMany()
.HasPrincipalKey(u => u.ResourceId);
modelBuilder.Entity<User>()
.HasMany<UserInvite>()
.WithOne(ui => ui.User)
.HasPrincipalKey(u => u.ResourceId);
modelBuilder.Entity<User>()
.HasMany<UserInvite>()
.WithOne(ui => ui.User)
.HasPrincipalKey(u => u.ResourceId)
.HasForeignKey(ui => ui.UserResourceId);
modelBuilder.Entity<UserInvite>()
.HasOne(ui => ui.User)
.WithMany()
.HasPrincipalKey(u => u.ResourceId)
.HasForeignKey(ui => ui.UserResourceId);
Modify Migration Script
Modifying the migration script ends up confusing EF when you attempt insert a record, I'm guessing it's expecting the User.Id column to be the foreign key principal column.
public class Test
{
public int Id { get; set; }
public int? UserResourceId { get; set; }
[ForeignKey(nameof(UserResourceId))]
public User? User { get; set; }
}
principalColumn has been changed from Id to ResourceId.
migrationBuilder.CreateTable(
name: "UserInvite",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
UserResourceId = table.Column<int>(type: "int", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Tests", x => x.Id);
table.ForeignKey(
name: "FK_Tests_Users_UserResourceId",
column: x => x.UserResourceId,
principalTable: "Users",
principalColumn: "ResourceId");
});
Update
It seemed like explicitly defining the relationship between Resource and User was necessary for this to work. Without that defined, EF wanted to create ResourceId1 to represent the second relationship on User.ResourceId.
This works
public class Resource
{
public int Id { get; set; }
}
public class User
{
public int Id { get; set; }
public int ResourceId { get; set; }
public Resource Resource { get; set; } = default!;
}
public class UserInvite
{
public int Id { get; set; }
public int? UserResourceId { get; set; }
public User? User { get; set; }
}
public class UserInviteConfiguration : IEntityTypeConfiguration<UserInvite>
{
public void Configure(EntityTypeBuilder<UserInvite> builder)
{
builder.HasOne(x => x.User)
.WithMany()
.HasPrincipalKey(x => x.ResourceId)
.HasForeignKey(x => x.UserResourceId);
}
}
public class UserConfiguration : IEntityTypeConfiguration<User>
{
public void Configure(EntityTypeBuilder<User> builder)
{
builder.HasOne(x => x.Resource)
.WithOne()
.HasForeignKey<User>(x => x.ResourceId);
}
}
This generates the following SQL script
CREATE TABLE [dbo].[Resource] (
[Id] int NOT NULL IDENTITY,
CONSTRAINT [PK_Resource] PRIMARY KEY ([Id])
);
GO
CREATE TABLE [dbo].[User] (
[Id] int NOT NULL IDENTITY,
[ResourceId] int NOT NULL,
CONSTRAINT [PK_User] PRIMARY KEY ([Id]),
CONSTRAINT [AK_User_ResourceId] UNIQUE ([ResourceId]),
CONSTRAINT [FK_User_Resource_ResourceId] FOREIGN KEY ([ResourceId]) REFERENCES [dbo].[Resource] ([Id]) ON DELETE CASCADE
);
GO
CREATE TABLE [dbo].[UserInvite] (
[Id] int NOT NULL IDENTITY,
[UserResourceId] int NULL,
CONSTRAINT [PK_UserInvite] PRIMARY KEY ([Id]),
CONSTRAINT [FK_UserInvite_User_UserResourceId] FOREIGN KEY ([UserResourceId]) REFERENCES [dbo].[User] ([ResourceId])
);
GO
CREATE INDEX [IX_UserInvite_UserResourceId] ON [dbo].[UserInvite] ([UserResourceId]);
GO
EF automatically creates the Unique Constraint on User.ResourceId, which is required for it to be key column for UserInvite.UserResourceId
Since each Resource can only be associated to a single User, that relationship is a 1:1.
EF automatically named the unique constraint for the principal key with an AK prefix, indicating that constraint is used to enforce an Alternate Key.
FYI: Although the relationship can be configured from either side, I'm a big proponent of configuring the relationship on the entity that contains the FK column. I find it makes the configurations more intuitive and reduces the bloat in the PK configuration for frequently referenced entities.
/Update
Just to make sure I'm understanding... you want to link UserInvite.UserResourceId to the non-key column ResourceId in the User table. User has a PK of Id. User.ResourceId is a FK reference to another table (Resource?) in which ResourceId is the PK. Posting your definitions for all three classes would have been helpful.
modelBuilder.Entity<UserInvite>()
.HasOne(ui => ui.User)
.WithMany(u => u.UserInvites)
.HasPrinicipalKey<User>(u => u.ResourceId)
.HasForeignKey<UserInvite>(ui => ui.UserResourceId);
Putting the < Type > in the clause explicitly tells EF which entity has the key. Using HasPrincipalKey/HasForeignKey without the explicit type requires EF to assume where the property exists. If it guesses the wrong side and can't find the field, it will create one.
Also note that when EF creates a numbered shadow property, it sees the original field but "knows" it can't use it for the relationship, so it creates a new field suffixed with a number. This usually happens when there is a navigation property List<UserInvite> UserInvites , but the relationship was defined without the property... .WithMany() instead of .WithMany(x=>x.UserInvites).
Since your configuration created User.ResourceId1, you may want to validate your model as EF is seeing a second relationship for User.ResourceId. I suspect that this is happening because your configuration did not include the HasForeignKey clause. EF saw that ResourceId already existed in the model, but it is not defined as the FK, so it created ResourceId1 to represent the FK.
FYI: User.ResourceId must be unique to be used as a principal key. You may want to add an explicit unique constraint. I'm not sure if EF does that automatically.
I am trying to change my primary key in one of tables from an int to uniqueidentifier. As pointed out in the title, I am taking a database first approach using entity framework.
The process I took was to remove the primary key from the table in sql designer and renamed the column "itemID" to "item".
I then created another column named "itemID" and set this to be a uniqueidentifier type with default to newsequentialid().
Then I deleted the column that I renamed previously to "item" and set "itemID" as the primary key.
I then moved back to visual studio and did an update model from database which gave me an error
Error 1 Error 2019: Member Mapping specified is not valid. The type 'Edm.Int32[Nullable=False,DefaultValue=]' of member 'itemID' in type 'ShoppingModel.dbFruits' is not compatible with 'SqlServer.uniqueidentifier[Nullable=False,DefaultValue=,StoreGeneratedPattern=Identity]' of member 'itemID' in type 'ShoppingModel.Store.dbFruits'.
and here is my model from under the .tt directory
public partial class dbFruits
{
public dbFruits()
{
this.dbCart = new HashSet<dbCart>();
}
public int itemID { get; set; }
public string name { get; set; }
public string price { get; set; }
}
I've run into similar issues before, and found that the way to solve it was to delete the table from the model. Save and close the model. Then reopen the model and re-add the table.
A SQL Server uniqueidentifier is the same datatype as a C# Guid. You need to change
public int itemID { get; set; }
to
public Guid itemID { get; set; }
I am having this Entity (both in database and Entity Framework):
public class LanguageValue
{
public int ID { get; set; }
public long Key { get; set; } // bigint in database
public int LanguageID { get; set; } // FK with a Language table in database
public string Value { get; set; } // nvarchar(MAX) in database
public bool Active { get; set; } // bit in database
}
I have already read this article, but my problem is a bit different: EF6: How to generate a unique number automatically based on entity Id
My Key column does not have unique constraint, because there can be multiple rows with the same Key value. For example:
ID Key LanguageID Value
---------------------------------------------------
1 1 1 Name in Language 1
2 1 2 Name in Language 2
I cannot use a Mapping table to enforce a FK instead of Key because multiple tables uses this same table (Product's Name, Category's Name, Article's Content).
Now whenever I need to insert a Product or Category record, I need to insert their corresponding Language Value. However, I have yet to find a way to generate a Key that is unique among them, and more over, need to be unique in case two insert are being processed at once (for example, adding a Product and Category at the same time).
I am thinking about Guid, should that be my safe bet with RNG, or is there any better way/design for achieving it?
OK, I think my problem was from bad database design. I seperated the LanguageValue table into two tables, like the following diagram, and realize 2 pros that the previous design did not have:
I can now safely insert the LanguageKey with IDENTITY.
I can now have FK for Product and Category's NameLanguageKey, which were impossible before because Key was not unique.
Say I have two tables:
Products
[ProductID] PK
[Weight]
[ProductCode]
and
KnownProductCodes
[ProductCode] PK
[Description]
Now I want my Product entity to have a KnownProductCodeDetails property. BUT the interesting thing here is that Products.ProductCode may contain EITHER product codes that DO exist in the KnownProductCodes table, OR the product codes THAT DON'T EXIST in KnownProductCodes table.
So, my question is: how do I create such a relationship between the two entities in Entity Framework?
PS. By the way, is it possible for an entity to have a foreign relationship without having a corresponding constraint in the database?
Thanks!
==
Details: EF 6.1.2, Code first
Such an association wouldn't be a foreign key.
A FK is a contraint, it uses an entity's primary key values to restrict the domain of values in the referencing entity. However, you don't want the values Product.ProductCode to be constrained, so this field can't be a foreign key by definition. (Nor technically).
A second point is that meaningful primary keys, like KnownProductCodes.ProductCode, are nearly always a bad idea, because one day the business may demand to change their values. And changing primary key values is a hassle.
So the obvious thing here would be to create a real nullable foreign key to a new primary key field, KnownProductCodesId. Then you can get the display value for a product's product code either from this FK (if not null) or Product.ProductCode. And modifying KnownProductCodes.ProductCode is easy now.
Another approach could be to create a "free association". Let this be your classes:
public class Product
{
public int ProductID { get; set; }
public decimal? Weight { get; set; }
public string ProductCode { get; set; }
public virtual KnownProductCode KnownProductCode { get; set; }
}
public partial class KnownProductCode
{
public string ProductCode { get; set; }
public string Description { get; set; }
}
Now in the mappings you can define an association between them:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<KnownProductCode>().HasKey(k => k.ProductCode);
modelBuilder.Entity<Product>()
.HasOptional(p => p.KnownProductCode)
.WithMany()
.HasForeignKey(p => p.ProductCode);
}
But in the database you avoid creating the actual FK. EF will allow that, it only wants associations to point to an entity's primary key, but the association doesn't have to be a hard FK in the database.
(Note however that this takes special measures if you create the database from the model, I wouldn't recommend it).
I am using CodeFirst in my project. One of the things I am learning is how I can design my tables by first writing classes. My question is - how can I classify the primary key [key] Id, as an auto increment field. So that when a record is created (or a row in the table) the primary key is auto generated. How do I do this in codefirst while writing class definition. Thanks for the help.
public class NewTable
{
//Looking for something like [AutoIncrement][key] for Id field etc...
[key]
public int Id { get; set; }
[Required(ErrorMessage = "Title is required")]
[DisplayName("Title")]
public string Title { get; set; }
}
A string auto increment? That's not gonna work.
Use int instead, and the PK will be an identity column by default. You don't need the [Key] attribute either; EF will infer that because the property is called Id.