Primary key has to be called "Id" using EFCode? - asp.net

I'm writting an application using ASP MVC 3 and based on the music store tutorial. I installed the EFCode framework and I created a database by right clicking App_Data folder.
The columns of the Table "Client" are
IdClient
Name
IdClient was defined as primary key by right clicking on it, and Identity was set to Yes and autoincrement, etc. Everything seems fine...When I run the application it tells me that this table has no key defined!!
If i rename IdClient to Id there is no problem, my question why doesn't it detect IdClient as primary key?? In the tutorial database the primary keys are not defined with a name "Id"...
Thanks!

I assume you mean Entity Framework Code First.
You can add the [Key] attribute to the column.
public class Product
{
[Key]
public int TestID { get; set; }
}
Entity Framework Code First uses convention over configuration and by default will look for a column named "ID" to make it the primary key. Otherwise you have to it declaratively.

You have to do one of two things
1) Use DataAnnotations, and in your model class give your idClient property the [Key] attribute. That will tell EF that idClient is your primary key.
2) In your data context's class, you can override the OnModelCreating(ModelBuilder modelBuilder) method. In that method you have to call something like modelBuilder.Entity<MyEntity>().HasKey(x => x.idClient); so EF knows that this is an identity and key column.
By default, EF4 Code First only automatically sets a column as a primary key if it is named Id or <entity name>Id.

Related

Identity MySQL EF Pomelo Core 2.2 - Two user tables to one UserId FK relationship not displaying user results

I have three MySQL tables that all appear to have been generated correctly with .Net Core 2.2. code first with Pomelo/EF framework:
AspnetUsers with PK=UserId (default Identity Users table with Id
changed to UserId)
UserSetting with PK=UserId
I originally had these as one User table on my last project and wanted to leave Identity alone as much as possible and so I created a second table to hold other user settings.
The problem exists on my third table called Incident with this FK relationship currently:
public class Incident
{
[Key]
public int IncidentId { get; set; }
...
public string UserId { get; set; }
...
[ForeignKey("UserId")]
public virtual IdentityUser User { get; set; }
[ForeignKey("UserId")]
public virtual UserSetting UserSetting { get; set; }
}
So, ideally I'll be able to pull values from both the AspnetUsers table and the UserSetting table to form one complete user. However, when trying to do this:
IQueryable<Incident> incident = _context.Incident.OrderByDescending(d => d.IncidentDate);
And then get at either:
incident.User (e.g. incident.User.Username)
incident.UserSetting (e.g. incident.UserSetting.IPAddress)
I get a NullReferenceException. I think EF is confused or maybe I am... but when I remove the annotations and let EF try to sort it out, I get this error message when running add-migration:
Both relationships between 'Incident.User' and 'IdentityUser' and
between 'Incident.UserSetting' and 'UserSetting' could use {'UserId'}
as the foreign key. To resolve this configure the foreign key
properties explicitly on at least one of the relationships
I tried several things and none the wiser. I've definitely checked that the UserId value matches in all three tables (so it's not null because it's actually null). When I look in the debugger output I don't see any joins being done on the select statement.
I thought about creating a FK relationship between UserSetting and the AspnetUsers table (e.g. incident.User.Usersetting.IPAddress), but again, trying to get away from the tweaking of Identity which appears to be mostly invisible without scaffolding it.
How do I link both my user tables to my Incident table using one UserId property in that Incident table? Is this maybe a bad idea (i.e. should I just go back to using a single user table)? Thanks.
Rookie mistake... I was converting a four year old project from .NET Framework to .NET Core. .NET Framework doesn't require the .Include() statements. So, I simply changed:
IQueryable<Incident> incident = _context.Incident.OrderByDescending(d => d.IncidentDate);
To:
var incident = _context.Incident
.Include(u => u.User)
.Include(u => u.UserSetting)
.OrderByDescending(d => d.IncidentDate);

EF6 Code First throwing NullReferenceException when no PRIMARY KEY exists

This is a bit of a strange one. I do not have administrative access on the database and am working with a table that is properly constrained, but has no primary key defined.
The schema is as follows:
CREATE TABLE Foo
(
KeyColumn VARCHAR(100) NOT NULL UNIQUE,
BitValue BIT NOT NULL
)
Within EF, there's a model:
[Table("Foo")]
public partial class FooModel
{
[Key] //Also tried by setting this in the ModelBinder as well with no luck
public string KeyColumn {get;set;}
public bool BitValue {get;set;}
}
//Within DbContext subclass:
public DbSet<FooModel> {get;set;}
//When in code:
context.FooModel throws NullReferenceException.
I believe this is because EF cannot map to the underlying table in spite of the identical schema. KeyColumn is a valid key, but is not defined as explicitly as the PRIMARY KEY.
Is there a way to force EF CodeFirst to map to this underlying table?
I was able to solve this through using the leaky abstraction provided by EF6.
var m = context.FooModel.SqlQuery(#"
SELECT KeyColumn
, BitValue
FROM Foo
WHERE KeyColumn = #KeyColumn
", new SqlParameter("#KeyColumn", keyColumnValue)).FirstOrDefault();
Other operations, such as adding and saving models seemed to work after this.

can I add my own classes to entity framework?

I wanted to start using Entity Framework for my projects. A new project which we'll be starting soon, will have an Employee table. I was initially planning to have a IEmployee Interface, which will be implemented by a Manager and Staff classes, which will allow different functionality but will both store data in the Employee table, with a flag in the table distinguishing them.
If I use DB First, and design my Employee table and then use Entity Framework, i know the .tt file will have a partial class Employee. I could then make my own Manager and Staff classes which implement the partial class Employee. But then how would I store that back in the db using Entity Framework? Could I just do something like
// currentManager would be the manager object
dbContext.Emplyee.Add(currentManager);
dbContext.SaveChanges();
would entity framework be ok with this, even though i'm passing a Manager object into Employee to save? Or is there a better way to do this? And same with retrieving, how could I use Entity Framework to get back a Manager or Staff? Would I need to get a Employee back first and then cast it? Something like
var employee = from employees... // get employee
Manager currentManager = (Manager)employee;
Yes, you can use EF DB first and have multiple classes derived from a common base class that are stored in the same database table.
The "flag" you envision is called a discriminator by EF. It is a column in the table that specifies which subtype the record is an instance of.
With database first, you need to tweak the model generated by EF to get this working, but it's fairly straightforward. I think the easiest way to set this up is to
Create the database model in SQL, being sure the Employee table has a NOT NULL property like EmployeeType that can be used as the discriminator. I think this can be any type, but an int will work fine.
Create your EF model ( Add | New Item... | Data | ADO.NET Entity Data Model ), and map the Employee table (and anything else you need).
Double click the generated .edmx file to open the entity framework designer.
Right mouse click on the canvass and select Add New... | Entity and create a Manager entity that derives from Employee. Repeat for Staff. Your designer should look like this:
Right mouse click on Manager and select Table Mapping. In the mapping details, specify that it maps to Employee and add a condition that is When EmployeeType = 1. Do the same for Staff, but make the mapping When EmployeeType = 2.
Last, you need to delete the EmployeeType property from the Employee mapping.
That being done, you can extend the Manager and Staff classes (that will now be generated by EF as partial classes) to have whatever business logic you want, and do queries/etc with EF via the Employees mapping:
public class Manager : Employee
{
public void customManagerMethod() { }
}
public class Staff : Employee
{
public void customStaffMethod() { }
}
class Program
{
static void Main(string[] args)
{
using (var db = new dbfirstEntities())
{
Manager m = new Manager
{
FirstName = "Joe",
LastName = "Bigshot"
};
Staff s = new Staff
{
FirstName = "Joe",
LastName = "Schmoe"
};
db.Employees.Add(m);
db.Employees.Add(s);
db.SaveChanges();
}
}
}

Entity Framework 5: Using DatabaseGeneratedOption.Computed option

I have an EF5 code first project that uses the [DatabaseGenerated(DatabaseGeneratedOption.Computed)] attribute.
This option is overriding my settings.
Consider this SQL table:
CREATE TABLE Vehicle (
VehicleId int identity(1,1) not null,
Name varchar(100) not null default ('Not Set')
)
I am using the SQL default construct to set the [Name] is case it is not set.
In code behind, I have a class defined similar to:
public class Vehicle {
...
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public string ShoulderYN { get; set; }
}
When I update the entity in code, the value set in the default overrides my new setting.
In code, I have (pseudo):
vehicle.Name = 'Update Name of Vehicle';
_dbContext.Update(vehicle);
_dbContext.SaveChanges();
The expected result is Vehicle.Name = 'Update Name of Vehicle'.
The actual result is Vehicle.Name = 'Not Set'.
Is there a way in EF5 to say:
if Vehicle.Name is null/empty, use the value defined in the database? Otherwise, if I set the value in code, I want to use this value.
Apparently, no there isn't. It's not that smart :)
As you may already read, Computed option just tells the EF not to update your column, because you will compute a value on the DB-side yourself. EF will then just return newly computed value from your database (which in your case is "Not Set").
Your basic three options are - as per EF Source code documentation:
None - The database does not generate values.
Identity - The database generates a value when a row is inserted.
Computed - The database generates a value when a row is inserted or updated.
https://github.com/aspnet/EntityFramework6/blob/527ae18fe23f7649712e9461de0c90ed67c3dca9/src/EntityFramework/DataAnnotations/Schema/DatabaseGeneratedOption.cs
Since you expect a little more custom logic to be done, I'm afraid you would have to do it yourself. I would suggest you stop relying on database default constraint and do everything in code first approach. This way you would have a code like that:
public class Vehicle
{
public Vehicle()
{
this.Name = "Not set";
}
// Without 'Generated' attribute
public string Name { get; set; }
}
This way, when your Entity is created, it automatically starts with expected default value. And can be later changed by simply modifying the Name property.
Hope it helps!
Actually there is a simple solution for this:
You need to leave default constraint with value in table creation script as it is now:
CREATE TABLE Vehicle (
VehicleId int identity(1,1) not null,
Name varchar(100) not null default ('Not Set')
)
Just remove DatabaseGenerated attribute from property in class definition:
public class Vehicle {
...
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public string ShoulderYN { get; set; }
}
And that's it: now database will use default value only if you do not specify some value in code. Hope this helps.
I checked this for hours to get good answer but no:
EF cannot update models by automatic generated-ID.
You have 3 options:
Adding another VehicleId to Vehicle model.
Change automatic generated-ID to be manual generated by you.
Setting unique identifier to be something else then the generated-ID in your
model.
In your Vehicle Class it can be the Name property.
I suggest you option 3:
Setting up unique-id to be Vehicle.Name (and you can add more properties).
Then: if vehicle by unique-id doesn't exists, add new vehicle to db-context:
//if there is no such a Vehicle in system, add it:
if (vehicle.Name !=null && vehicle.Name != String.Empty && _dbContext.Where(v => v.Name == vehicle.Name).FirstOrDefault() == null)
_dbContext.Add(vehicle);
_dbContext.SaveChanges();

ASP.Net Dynamic Data IS showing my primary keys for every table when using Entities

Using a very run-of-the-mill database, with identity int for primary keys, a Dynamic Data Entities Project (EntityFramework) displays the primary key for view and edit. When using Linq to Sql, the primary key fields are not displayed.
I would like to hide the primary keys and use Entity Framework (VS 2008, .Net 3.5 sp1).
thanks
Use ScaffoldColumnAttribute to not scaffold a column.
You'll need to either customize code generation (easier in EF 4) or use a buddy class for this.
[MetadataType(typeof(MyEntity_Metadata))]
public partial class MyEntity
{
}
public class MyEntity_Metadata
{
[ScaffoldColumn(false)]
public int Id { get; set; }
}

Resources