5
votes

I'm using EF5 with VS2012 and I'm facing a problem when the tables get generated.

1)I create an easy database schema (edmx) that contains 2 tables:

  • Table1: Person
  • Attribute: Id (Guid)
  • Attribute: Name (string)

  • Table2: Role

  • Attribute: Id (Guid)
  • Attribute: Type (string)
  • Attribute: PersonId (Guid) (association with the table Person)

2)defining the properties of the unique key (called Id) as:

  • Concurrency Mode: None
  • Default Value: None
  • Entity Key: True
  • Getter: Public
  • Name: Id
  • Nullable: False
  • Setter: Public
  • StoreGeneratedPattern: Identity
  • Type: Guid (I have also tried with Int32)

3)And the properties of the Entity model are:

  • Code Generation Strategy: None
  • Database Generation Workflow: TablePerTypeStrategy (VS)
  • Database Schema Name: dbo
  • DDL Generation Template: SSDLToSQL10.tt (VS)
  • Entity Container Access: Public
  • Entity Container Name: DatabaseSchemaContainer
  • Lazy Loading Enabled: True
  • Metadata Artifact Processing: Embed in Output Assembly
  • Namespace: DatabaseSchema
  • Pluralize New Objets: False
  • Transform Related Text Templates on Save: True
  • Update Property Facets: True
  • Validate On Build: True

4)the related classes are generated, but the [Key] attribute is not present:

using System;
using System.Collections.Generic;

public partial class Person
{
    public Person()
    {
        this.Role = new HashSet<Role>();
    }

    //[Key] <-- Missed!
    public System.Guid Id { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Role> Role { get; set; }
}

5) I create a Domain service to expose the above entities to the client, like:

[EnableClientAccess]
public class DomainService1 : DomainService
{
    [Query]
    public IEnumerable<Person> GetPersonSet()
    {

    }

    [Update]
    public void UpdatePerson(Person person)
    {

    }

    [Insert]
    public void InsertPerson(Person person)
    {

    }

    [Delete]
    public void DeletePerson(Person person)
    {

    }
}

6) Rebuilding and getting the error:

The Entity 'Person' in DomainService 'DomainService1' does not have a key defined. Entity types exposed by DomainService operations must have at least one public property marked with the KeyAttribute.

Any suggestion is appreciated!

Ale

3

3 Answers

6
votes

You may try to change code of the .tt generation template and add attributes to classes at time of generation. In your case you may change the method for properties generation like that:

public string Property(EdmProperty edmProperty)
{
    return string.Format(
        CultureInfo.InvariantCulture,

        //Custom check for key field
        (_ef.IsKey(edmProperty) ? "[Key]" : "") +

        "{0} {1} {2} {{ {3}get; {4}set; }}",
        Accessibility.ForProperty(edmProperty),
        _typeMapper.GetTypeName(edmProperty.TypeUsage),
        _code.Escape(edmProperty),
        _code.SpaceAfter(Accessibility.ForGetter(edmProperty)),
        _code.SpaceAfter(Accessibility.ForSetter(edmProperty)));
}

and add namespace declaration to each generated class:

public string UsingDirectives(bool inHeader, bool includeCollections = true)
{
    return inHeader == string.IsNullOrEmpty(_code.VsNamespaceSuggestion())
        ? string.Format(
            CultureInfo.InvariantCulture,

            //Namespace for KeyAttribute goes here
            "{0}using System; using System.ComponentModel.DataAnnotations;{1}" +
            "{2}",
            inHeader ? Environment.NewLine : "",
            includeCollections ? (Environment.NewLine + "using System.Collections.Generic;") : "",
            inHeader ? "" : Environment.NewLine)
        : "";
}

Once it done you can click right button on .tt and select "Run custom tool"

1
votes

While this answer was originally from EF4, I suspect it's still the case:

T4 Templates doesn't use data annotations because classes generated from templates don't need them. (source)

I suspect this may also be related to the fact that in code first you do not need the KeyAttribute unless you are using key fields which don't follow conventions (e.g. Id and PersonId are automatically used as keys on a Person entity). If you're not too far down the model-first route, perhaps consider using code-first?

0
votes

vs2012 is not the right tool (yet?) to create database models. You can better use visio (Not 2013!) or SQL Server Management Studio. And you do not need it, 99% of the work of data modelling is creating the right model, not what Vs2012 tries, to automate the small step to c#.

That is the reason that obvious features like you need, are not included in vs2012. And maybe it is never possible, because vs2012 is targeted for code first developers.