Generating Primary key without set it as key - sql

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

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.

EF database first code generation missing Key and data annotation

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; }

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?

Duplicated reference key - Fluent NHibernate Automapping

I got a problem with automapping in fluent and reference key. Example would be that:
public class ConfigurationCategory
{
public virtual Guid Id { get; private set; }
[NotNull]
public virtual String Name { get; set; }
public virtual String Description { get; set; }
public virtual String Icon { get; set; }
public virtual ConfigurationCategory Parent { get; set; }
public virtual IList<ConfigurationCategory> Children { get; private set; }
public ConfigurationCategory()
{
Children = new List<ConfigurationCategory>();
}
}
Results in the following SQL-Output:
CREATE TABLE "ConfigurationCategory"
...
parent_id uuid,
configurationcategory_id uuid,
CONSTRAINT "ConfigurationCategory_pkey" PRIMARY KEY (id),
CONSTRAINT fk6ccc850055890dc8 FOREIGN KEY (configurationcategory_id)
REFERENCES "ConfigurationCategory" (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT fk6ccc8500ee71b726 FOREIGN KEY (parent_id)
REFERENCES "ConfigurationCategory" (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
Why is ConfigurationCategory duplicated?
I haven't used fluent automapping, but I would guess it is confused by the fact that you have both the Parent and the Children properties; I would guess fluent can't tell that they are both meant to be handled by the same column in the database.
You probably need to create a ClassMap and specify the key column names for both the References() and HasMany() calls.

Composite primary key scenario

I need a many to many structure, but with an aggregate constraint.
What i'm trying to accomplish is done easily in pure sql, but since ActiveRecord discourages composite primary keys, i'm not sure how to accomplish what i need in recommended style.
Here is what i would have in pure sql:
table Project (ID int)
table Report (ProjectWideID nvarchar(50), ProjectID int, primary key (ProjectWideID, ProjectID))
table ChosenReport(ListOrder int, ProjectWideReportID, ReportID, primary key (ProjectID,ProjectWideReportID))
This means that a project has many reports.
Each report has an assigned id, which is unique inside a project.
Project has many chosen reports as an ordered list, each of them references a report in the same project by it's project-wide assigned report id.
But here is my ActiveRecord classes, and something is missing here.
[ActiveRecord]
public class Project
{
[PrimaryKey]
public int ID { get; set; }
[HasMany] IList<Report> Reports { get; set; }
[HasMany] IList<ChosenReport> ChosenReports { get; set; }
}
[ActiveRecord]
public class Report
{
[PrimaryKey]
public int ID { get; set; }
[BelongsTo("ProjectID")]
public Project ParentProject { get; set; }
// ... other properties
}
[ActiveRecord]
public class ChosenReport
{
// This one must be a key property
[BelongsTo("ParentProjectID")]
Project ParentProject { get; set; }
// This one must be a key property
[BelongsTo("ParentProjectID")]
Report ParentReport { get; set; }
// ... other properties
}
Now, since i have surrogate keys, i don't know how to constraint ChosenReport so it can't have reference to a report from different project. So i have to enforce constraints in domain. Do i have any other options for this with ActiveRecord?
The true ActiveRecord way of doing this would be making your classes inherit from ActiveRecordBase<T> and then overriding OnSave() and implementing your checks there. But I recommend implementing the checking logic in a NHibernate interceptor or event listener instead.