System.Data.Entity.Edm.EdmEntityType: : EntityType 'MyRecord' has no key defined. Define the key for this EntityType - sql-server

I am attempting to connect to a SQL Server database from my MVC app. I keep getting this error:
System.Data.Entity.Edm.EdmEntityType: : EntityType 'MyRecord' has no key defined. Define the key for this EntityType. I googled it and founf that this error occurs when one did not define get and set for the key inside the class. That's not true in my case since I have them defined. Below is my sample class:
[Table("DataRecords")]
public class MyRecord
{
public string RecordID { get; set; }
public string RecordDesc { get; set; }
public float PageNo { get; set; }
}
I also have MyRecordContext class:
public class MyRecordContext : DbContext
{
public DbSet<MyRecord> MyRecords { get; set; }
}
And a controller with "Details" action:
public ActionResult Details(string _id)
{
MyRecordContext rc = new MyRecordContext(); <-- ERROR HERE
MyRecord r = rc.MyRecords.Single(x => x.RecordID == _id);
return View(r);
}
I call it as : http://localhost:57802/Home/Details/01-019-2-1111-00-00
Can anyone help diagnose the issue?

The error tells you the exact problem. There's no key defined on your entity. Entity Framework uses certain conventions to automatically decipher which property should be the primary key, however, since your entity here is named MyRecord, EF will look for a property named something like MyRecordID, not RecordID. If your class and/or property name does not conform to conventions, then you have to tell EF explictly what to use:
[Key]
public string RecordID { get; set; }
UPDATE
If you have a composite key, then, you just have to specify the column order as well:
[Key, Column(Order = 1)]
public int Key1 { get; set; }
[Key, Column(Order = 2)]
public int Key2 { get; set; }

Related

Null data returned using a 1:1 model

I have two SQL tables, User and UserType joined with UserType as a foreign key, with their respective models in ASP. To my understanding, this should be a 1:1 relationship (correct me if I'm wrong). One unique user, set as a type of user (being admin, super admin, user etc).
When I try and retrieve a list of users, it returns a null on the property UserType.
I used Google to get this far, but I'm struggling to get this particular issue fixed.
At one point I got an error stating: "Unable to determine the principal end of an association". To get around that, I included a Required annotation (didn't work) and a ForeignKey annotation (didn't work either) in both models, both simultaneously and separately.
This is what I have so far.
[Table("Users", Schema = "dbo")]
public class Users
{
[Key, ForeignKey("UserType")]
public Guid Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string ContactNumber { get; set; }
public UserType UserType { get; set; }
public string IsActive { get; set; }
}
[Table("UserType", Schema = "dbo")]
public class UserType
{
[Key]
public Guid Id { get; set; }
public string Type { get; set; }
public string Description { get; set; }
public string IsActive { get; set; }
public Users Users { get; set; }
}
I'm using the below LINQ method to retrieve the data:
public PagedTables<Users> GetAllUsers(Pagination pagination)
{
using (var db = new DbContext())
{
var user = new PagedTables<Users>()
{
Data = db.Users.OrderBy(U => U.Id).Skip(pagination.Page).Take(pagination.Limit).ToList(),
Count = db.Users.Count()
};
return user;
}
}
A break point on the users var shows that the property UserType returns null. I would expect the assigned user type to be joined onto the user.
Any help would be appreciated. Thanks
My EF background is database-first but if you are eager loading (i.e. not lazy loading) then are you missing an Include to tell LINQ to go and get the UserType? Something like;
Data = db.Users.OrderBy(U => U.Id).Skip(pagination.Page).Take(pagination.Limit).Include(U => U.UserType).ToList(),

Primary Key based on Foreign Keys EF

In the beginning I've tried, as below, but still without result:
Defining two foreign keys as primary key in Entity Framework
Entity Framework Two foreign keys as primary key
Here is my entity:
public class Passage
{
[Key, ForeignKey("FromID")]
public Localization From { get; set; }
public int ToID { get; set; }
[Key, ForeignKey("ToID")]
public Localization To { get; set; }
[Required]
public string HourForm { get; set; }
[Required]
public string HourTo { get; set; }
[Required]
public int Seats { get; set; }
[Required]
public char Weekend { get; set; }
public int? AdditinalTime { get; set; }
public int FromID { get; set; }
}
I am trying to create primary key based on two foreign keys. There is an error
EntityType 'Passage' has no key defined. Define the key for this EntityType.
What am I doing wrong?
Quoting directly from your first link:
"Primary keys always must be defined by scalar properties in the entity class. You cannot refer to the PKs by navigation properties alone."
So, you need to put the key attributes on the scalar values, not the navigation properties.
public class Passage
{
[Key, ForeignKey("From"), Column(Order = 0)]
public int FromID { get; set; }
public Localization From { get; set; }
[Key, ForeignKey("To"), Column(Order = 1)]
public int ToID { get; set; }
public Localization To { get; set; }
}
As one of quoted links said, you need to use the Column attribute to specify the order of your composite keys:
public class Passage
{
[Key,Column(Order=0), ForeignKey("From")]
public int FromId { get; set; }
[Key,Column(Order=1), ForeignKey("To")]
public int ToId { get; set; }
//...
}
I noticed now that you are using those attributes on the navigation properties, as #PaulAbbott said in his answer, the primary keys must be defined using scalar properties, in this case, the FK properties.

Entity Framework 6.1 - Code-First One-to-Many on single entity: Can't map PK to FK?

I'm trying to do a One-to-Many on a single table/entity using code first. My entity looks like this and works fine:
public class StockIndex
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[StringLength(45, MinimumLength = 3)]
public string Name { get; set; }
[StringLength(500)]
public string Description { get; set; }
public List<Component> Components { get; set; }
public StockIndex ParentStockIndex { get; set; }
public List<StockIndex> StockSubIndices { get; set; }
public StockIndex()
{
StockSubIndices = new List<StockIndex>();
}
}
It creates a table with a PK and FK, like you'd expect:
CREATE TABLE [dbo].[StockIndex] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Name] NVARCHAR (45) NULL,
[Description] NVARCHAR (500) NULL,
[ParentStockIndex_Id] INT NULL,
CONSTRAINT [PK_dbo.StockIndex] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_dbo.StockIndex_dbo.StockIndex_ParentStockIndex_Id] FOREIGN KEY ([ParentStockIndex_Id]) REFERENCES [dbo].[StockIndex] ([Id])
);
It works great. I've scaffolded all the CRUD for it and everything works. However, this forces me to fire an additional query in my controllers when doing an edit, in order to lookup and assign a "parent" record to the new one. I want access to the "ParentStockIndex_Id" field in table so I can assign it directly from a dropdown and skip the extra lookup query. I tried mapping it:
public class StockIndex
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[StringLength(45, MinimumLength = 3)]
public string Name { get; set; }
[StringLength(500)]
public string Description { get; set; }
public List<Component> Components { get; set; }
public int ParentStockIndex_Id { get; set; }
[ForeignKey("ParentStockIndex_Id")]
public StockIndex ParentStockIndex { get; set; }
public List<StockIndex> StockSubIndices { get; set; }
public StockIndex()
{
StockSubIndices = new List<StockIndex>();
}
}
But I get an exception when running it, when data is seeded in my DbContext:
Unable to determine the principal end of the 'MyApp.Models.StockIndex_ParentStockIndex' relationship. Multiple added entities may have the same primary key.
I'm sure I'm doing something wrong, but would like to do this without using Fluent, if possible.
You should use public int? ParentStockIndex_Id { get; set; }, to set the Parent not required (have you seen the question mark just after int).

How to add missing foreign key/entity? Save BreezeJs with JObjects

This is database first using entity frameworks 6 and lazy loading.
I have the following class of device that is missing four foreign key ids:
public partial class Device {
public int SolutionId { get; set; }
public string SiteId { get; set; }
public string Name { get; set; }
public int SysId { get; set; }
public Nullable<int> SysType { get; set; }
public string SerialNumber { get; set; }
public Nullable<int> ParentId { get; set; }
public virtual DeviceModel DeviceModel { get; set; }
public virtual DeviceType DeviceType { get; set; }
public virtual SolutionApplication SolutionApplication { get; set; }
public virtual SolutionType SolutionType { get; set; }
}
Missing Keys/Ids that are not generated but automatically got mapped as virtual objects:
DeviceModelId, DeviceTypeId, SolutionApplicationId, and SolutionTypeId
I want to save a new device using breeze but it is looking for the device type. I tried adding the deviceTypeId before saving:
newDevice.deviceTypeId = 5;
But it still doesn't get read and does not get saved.
[Error] Save failed: Entities in 'PortalEntities.Devices' participate in the 'FK_Devices_DeviceTypes' relationship. 0 related 'DeviceType' were found. 1 'DeviceType' is expected.
This is how my save statement in my breeze controller:
[HttpPost]
public SaveResult SaveChanges(JObject saveBundle)
{
return _repository.SaveChanges(saveBundle);
}
I checked what actually is getting passed as it attempts to do a save. The save bundled contained the following entity. BUT the device type which is a required field is not there, hence the error that its missing.
"entities": [
{
"SolutionId": -1,
"SiteId": "11111d2",
"Name": "asdf",
"SysId": 0,
"SysType": null,
"SerialNumber": null,
"ParentId": null,
"entityAspect": {
"entityTypeName": "Device:#HtPortal.Data.Portal",
"defaultResourceName": "Devices",
"entityState": "Added",
"originalValuesMap": {},
"autoGeneratedKey": {
"propertyName": "SolutionId",
"autoGeneratedKeyType": "Identity"
}
}
}
Since the deviceTypeId did not work, so I tried adding the deviceType right before saving:
newDevice.deviceType = { id:5, name: 'Blue'}; //NOTE: This already exists in the devicetype table in the database
But I get the following error:
TypeError: Cannot read property 'entityState' of undefined
Using Breeze, How do I add this foreign entity so that I can save this new device?
Edit 1: This is my DeviceType Class:
public partial class DeviceType {
public DeviceType() {
this.Devices = new HashSet<Device>();
}
public byte Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Device> Devices { get; set; }
}
Just add the existing DeviceType object from your dbContext.
Something like:
using (YourDbEntities context = new YourDbEntities())
{
Device newDevice = new Device();
//whatever initialisation you need do....
newDevice.DeviceType = context.DeviceTypes.Find(5)
// the above line assumes that id is PK for DeviceType and you want the entry
// with id==5 - if not, other ways such as DeviceTypes.Where(d=>d.Id==5).First()
// to find the object in your existing db will work too!
context.Devices.Add(newDevice);
context.SaveChanges();
}

How to add foreign key information to code first POCO to comply with RIA Services

My two classes are as follows
public class Client
{
public Guid Id { get; set; }
public String Name{ get; set; }
public virtual ICollection<Product> Products{ get; set; }
}
public class Product
{
public Guid Id { get; set; }
public String Model { get; set; }
public String Version { get; set; }
[ForeignKey("Client_Id")]
public virtual Client Client { get; set; }
[ForeignKey("Client")]
public Guid? Client_Id { get; set; }
}
And the DbContext class is this:
public class ClientContext : DbContext
{
public DbSet<Client> Clients { get; set; }
public DbSet<Product> Products { get; set; }
}
I have confirmed that this model works with the associated database for all the usual CRUD stuff.
I have created a RIA DoaminService class on the web site as so:
[EnableClientAccess]
public class ClientDomainService : DbDomainService<ClientContext>
{
public IQueryable<DomainModel.Product> GetProducts()
{
return this.DbContext.Controllers;
}
public IQueryable<DomainModel.Client> GetClients()
{
return this.DbContext.Clients;
}
}
When I build the silverlight application I get the error:
Unable to retrieve association information for assocation .... Only
models that include foreign key information are supported.
I thought that the [ForeignKey] attributes added to the Client and Client_Id properties on the Product class would satisfy the "include foreign key information" requirement.
What am I missing?
Assuming your code is complete, you are missing the other side of the Foreign key relationship... the [Key] attributes on the primary keys.

Resources