EF database first code generation missing Key and data annotation - sql

For EF 6.1 and above, when I add/reverse engineer-Entity model model/code generation in VS15 & Sql-Server 2k16 Database my entities are missing both Id, and auto increment data-annotations. Saw this and this Question on SO, but no answers, just that its a bug, I am seeking an option to generate the PK Key, Auto Increment.
Question: How can I ensure, that the Id key & Auto-increment options are added to the entities during the code generation? There are no data annotations except on the foreign keys! Can I also get EF to generate Composite keys?
What I did:
In the database, I added the Set primary key on the [Id] col as int,
I also set Identity true, seed 1, auto increment 1
E.g. missing primary key
//E.g. Reverse Eng. Generated code from ASP table
public partial class AspNetUsers
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public AspNetUsers()
{
this.AspNetUserClaims = new HashSet<AspNetUserClaims>();
this.AspNetUserLogins = new HashSet<AspNetUserLogins>();
this.AspNetRoles = new HashSet<AspNetRoles>();
}
// Missing Primary Key
public string Id { get; set; }
public Nullable<int> IdNumber { get; set; } ...
E.g. 2 Missing both Primary Key & Auto Increment
public partial class AuditNetEvent
{
//Reverse Generated code missing Primary Key & Auto Increment
public bigint Id { get; set; }
public System.DateTime InsertedDate { get; set; }

It seems that the tooling doesn't add annotations when the default conventions make them redundant. For an Id column the default is that it's PK and identity. I tried with a table not matching the conventions (deviating PK column name and no identity) and the annotations were added:
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int CstId { get; set; }

Related

How does migrationBuilder determine which indexes to create?

This is using asp.net core 2.0, EF, visual studio 2017, sql server 2016, and creating a db migration via package manager console using 'add-migration' tool within the Package Manager Console.
I have a simple many-to-many relationship configured as below, 2 tables and a third 'joining table':
public class TblTrack
{
public int ID { get; set; }
...
//Navigation properties
public List<TblProductItem> ProductItems { get; set; }
}
public class TblProduct
{
public int ID { get; set; }
...
//Navigation properties
public List<TblProductItem> ProductItems { get; set; }
}
public class TblProductItem
{
[Key]
[Required]
public int ProductID { get; set; }
[Key]
[Required]
public int TrackID { get; set; }
//Navigation properties
public TblProduct Product { get; set; }
public TblTrack Track { get; set; }
}
This is from the migration (generate in PMC) to create the joining table:
migrationBuilder.AddPrimaryKey(
name: "PK_tbl_ProductItems",
table: "tbl_ProductItems",
columns: new[] { "ProductID", "TrackID" });
migrationBuilder.CreateIndex(
name: "IX_tbl_ProductItems_TrackID",
table: "tbl_ProductItems",
column: "TrackID");
Please could someone explain:
What's the purpose of the index IX_tbl_ProductItems_TrackID?
Why was an index created for TrackID but not for ProductID?
Is there some other setting that determines which indexes will be created in the migration?
By default EF automatically creates Index (non-unique) on each property that is a foreign key reference.
Make sure that EF correctly created relation between TblProduct and TblProductItem(for example in SQL Server by expanding keys) - if not, specify relation explicitly using Fluent Api.
Regarding other setting you can require creating indexes using method in your Context class, but that index should be auto generated if foreign key relation is set.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<TblProductItem>()
.HasIndex(e => e.TrackID);
}
I'm struggling with the same thing. I found out that if I reversed the order of the keys (using Fluent, however) it would make an index for the second column instead.
So to me, it seems like there's a bug in the framework when using composite keys. It is the ForeignKey annotation that causes the index to be made, but in this process it seems to believe that the primary key is the FIRST column only (in that case, no extra index needed for a "primary key" column), so it only creates an index for the second. But the primary key is composite, so it should probably create an index for the first column too.
A workaround (if you really want the first column to be indexed too) is to do what's suggested in the accepted answer. Should the bug (AFAIK) be fixed later, I don't think it would cause a problem by trying to create an extra index or anything.

Auto generate GUID in mvc5 that uses EF

I have an mvc5 application that is connected to a EF database. Some fields in this database are meant to be autogenerated as declared in SQL, but when used in MVC and upon inserting records, the GUID only contains the value of 0 for all records. How can I resolve this? Any help will be appreciated. Thanks.
Model class:
public partial class Store
{
public int StoreID { get; set; }
public int CustomerID { get; set; }
public string StoreName { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public System.Guid StoreUID { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int StoreNumber { get; set; }
public string StoreLogo { get; set; }
public string StoreLogoPath { get; set; }
public string StoreAddress { get; set; }
public string StoreCity { get; set; }
public string StoreRegion { get; set; }
public string StoreCountry { get; set; }
public virtual Customer Customer { get; set; }
}
Both StoreUID and StoreNumber supposed to be autogenerated fields. Below is an example how its supposed to be when a new store is inserted, however currently, storeNumber and StoreUID both just return 0.
You need to add defaults to your database table to generate the fields.
ALTER TABLE [dbo].[Store] ADD DEFAULT (newid()) FOR [StoreUID]
ALTER TABLE [dbo].[Store] ADD DEFAULT (myfuncthatreturnsanint()) FOR [StoreNumber]
This isn't really an Entity Framework feature. EF needs to be aware of these column types to generate the appropriate SQL. What you require is something that's actually achieved from the database. For Model First, I got the auto generated int Id functionality by modifying the T4 template that ships with EF to write the appropriate SQL, but it really is database functionality. StoreNumber is a different case since SQL server only allows one identity column.
For your database, your StoreUID column specification should be:
StoreUID uniqueidentifier not null DEFAULT newid()
You don't specify if you're dealing with model first or code first, or if you're building something new, so you may have to modify your existing table for this.
EDIT
If you're using model first, ensure that in your model the Store Generated Column is set to Identity for the StoreUID value to be server generated. If not, and you're not worried about who/what creates the GUID, then create a default constructor for Store, if you don't already have one. Then in there add StoreUID = Guid.NewGuid();.
For StoreNumber, SQL server doesn't support multiple columns with auto incrementing integers. You'd need to research a number of strategies for inserting it.
A number are listed here and here. Essentially make StoreNumber a function of StoreID with Computed Columns, or use an independent Sequence:
ALTER TABLE Store DROP COLUMN StoreNumber;
GO
ALTER TABLE Store ADD StoreNumber AS StoreID + 550000;

invalid Column name Practice_PK

I have the below code where am working on an ASp.net MVC application
public class Element
{
/// <summary>
/// Primary Key
/// </summary>
[Key]
public int Pk { get; set; }
[ForeignKey("Practice_PK")]
[Display(Name = "Practices")]
public Practice Practice { get; set; }
[Display(Name = "Practices")]
public int Practice_PK { get; set; }
}
Database
CREATE TABLE [dbo].[Elements] (
[Pk] INT IDENTITY (1, 1) NOT NULL,
[Practice_PK] INT NULL,
CONSTRAINT [FK_dbo.Elements_dbo.Practices_Practice_PK] FOREIGN KEY ([Practice_PK]) REFERENCES [dbo].[Practices] ([PK]) ON DELETE CASCADE
);
GO
CREATE NONCLUSTERED INDEX [IX_Practice_PK]
ON [dbo].[Elements]([Practice_PK] ASC);
I am getting the Error "Invalid Column name Practice_PK" everytime i try to create, Edit a page. I know this has been addressed many times but the error itself is so ambiguous i dont know how to resolve.
I just resolved my issue .Basically the 'Practice_PK' returning the error was for another variable ElementType (Not included the code above ) that is of the type ElementType that should have had a Practice_PK varaible but did not

Generating Primary key without set it as key

When I create a table in entity framework, i am not set any key in the table. But, when the table created the id field in the table set as key, Why?
public class EntityBase
{
public long Id { get; set; }
public DateTimeOffset? DeletedOn { get; set; }
public string RefId { get; set; }
public DateTimeOffset CreatedOn { get; set; }
}
As mentioned here Entity framework automatically identifies the primary key based on ideal naming like Id in your case :-
As detailed in document :-
Other default conventions supported by EF include the ability to
automatically identify primary-key and foreign keys based on common
naming patterns (for example: an ID or DinnerID property on the Dinner
class will be inferred as the primary key). EF also includes smart
conventions for wiring-up association relationships between models.
For more information :-
http://blogs.msdn.com/b/efdesign/archive/2010/06/01/conventions-for-code-first.aspx

Fluent nHibernate - Wrong column name when self reference

The mapping on foreign key are made with the wrong name. Why?
Here's my classes:
The order of the properties seems to be important:
public class Person
{
public virtual Person Mother { get; set; }
public virtual IList<Item> Items { get; set; }
public virtual Person Father { get; set; }
}
public class Item
{
public virtual string Name { get; set; }
}
Here's the mapping with Fluent Nhibernate
AutoMap.AssemblyOf<Person>(new CustomAutomappingConfiguration())
When I look to the database, the foreign key in the table seems to be the name of the first property with the type Person after the property Items. Here's the SQL generated to create the table:
CREATE TABLE "Item" (Id integer primary key autoincrement
, Name TEXT
, Father_id BIGINT
, constraint FKC57C4A2B4586680 foreign key (Father_id) references Patient)
Thank you in advance for your help ;)
The solution I've found is to override the configuraton like this:
AutoMap.AssemblyOf<Person>(new CustomAutomappingConfiguration())
.Override<Person>(m => m.HasMany<Item>(x => x.Items).KeyColumn("Patient_Id"))
Does exist any solution to let the auto mapping work seamlessly? And how Fluent nHibernate works to choose the name of the foreign key's column?