michael
michael

Reputation: 647

database first - EntityType xxx has no key defined. Define the key for this EntityType

I have database with 80 tables (each table has got primary key). I have generated model in ASP.NET MVC project from database (Add - New Item - ADO.NET Entity Data Model). But in generated model I have 80 classes (for each table in database) without attribute [Key] for example:

//------------------------------------------------------------------------------
// <auto-generated>
//    This code was generated from a template.
//
//    Manual changes to this file may cause unexpected behavior in your application.
//    Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace Blog.Models
{
    using System;
    using System.Collections.Generic;

    public partial class Comments
    {
        public int CommentId { get; set; }        
        public string Content { get; set; }
    }
}

So I have errors: EntityType xxx has no key defined. Define the key for this EntityType.

I often change database and then model in project so I can't each time add [Key] attribute to 80 AUTOGENERATED classes - what can I do??

Upvotes: 7

Views: 6154

Answers (3)

Chris Schiffhauer
Chris Schiffhauer

Reputation: 17290

If your model contains any tables with multiple primary keys, you'll need to add the Column annotation to your .tt file near line 66 as well, like this:

var simpleProperties = typeMapper.GetSimpleProperties(entity);
if (simpleProperties.Any())
{
    var keyIndex = 0; // This is a new line
    foreach (var edmProperty in simpleProperties)
    {
        // The following if block is new
        if (ef.IsKey(edmProperty)) 
        {
#>          [System.ComponentModel.DataAnnotations.Key]
            [System.ComponentModel.DataAnnotations.Schema.Column(Order = <#=keyIndex.ToString()#>)]
<#
            keyIndex++;
#>
<#      }
#>
        <#=codeStringGenerator.Property(edmProperty)#>
<#
    }
}

Upvotes: 8

Tim
Tim

Reputation: 412

To expand on @Kelly's answer, I too had to change the template and since the template is generated from another template, one would need to change the source. There is a source template for each of the supported languages but I suspect most people will be able to get by with changing the English templates which are denoted by the LCID 1033.

The files I found were:

C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\ItemTemplates\CSharp\Data\1033\DbCtxCSEF6\CSharpDbContext.Types.tt                                                                                                                               
C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\ItemTemplates\Web\CSharp\1033\DbCtxCSWSEF6\CSharpDbContext.Types.tt                                                                                                                              
C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\ItemTemplatesCache\CSharp\Data\1033\DbCtxCSEF6\CSharpDbContext.Types.tt                                                                                                                          
C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\ItemTemplatesCache\Web\CSharp\1033\DbCtxCSWSEF6\CSharpDbContext.Types.tt                                                                                                                         
C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\VWDExpress\ItemTemplates\CSharp\Data\1033\DbCtxCSEF6\CSharpDbContext.Types.tt                                                                                                                    
C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\VWDExpress\ItemTemplates\Web\CSharp\1033\DbCtxCSWSEF6\CSharpDbContext.Types.tt                                                                                                                   
C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\WDExpress\ItemTemplates\CSharp\Data\1033\DbCtxCSEF6\CSharpDbContext.Types.tt                                                                                                                     
C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\WDExpress\ItemTemplates\Web\CSharp\1033\DbCtxCSWSEF6\CSharpDbContext.Types.tt

And to put the code snippet needed in better context, this is what my Simple Properties section changed to:

    var simpleProperties = typeMapper.GetSimpleProperties(entity);
    if (simpleProperties.Any())
    {
        foreach (var edmProperty in simpleProperties)
        {
            if (ef.IsKey(edmProperty)) 
            { 
#>
    [System.ComponentModel.DataAnnotations.Key]
<#

            }
#>
    <#=codeStringGenerator.Property(edmProperty)#>
<#
        }
    }

Upvotes: 5

Kelly
Kelly

Reputation: 985

I had same issue and solved it by adding the [Key] attributes into each class, but to avoid doing this manually, I modified the .tt file that is used to generate each of the classes. I added an if condition in the loop that loops through each simple property of the class. It adds the string "[Key]" before each primary key field. If you have a table with multiple fields making up the PK then you'd have to manually add the attributes for this ([Key, Column(Order = 0)]) or further work to update the .tt file (I was too lazy since I only have one table so far with a composite key). Once done, I saved the .tt file and it regenerated all of my classes and these errors went away.

foreach (var edmProperty in simpleProperties)
{
        if (ef.IsKey(edmProperty)) { 
#>           [Key]
<#      } 

Upvotes: 12

Related Questions