Das Generieren von POCO-Klassen aus dem Entity-Framework Modell klappt ja recht einfach.
Leider werden aber die Beschreibungen nicht als XML-Comments übernommen.

Aber es gibt eine Lösung: einfach die T4-Templates erweitern…

Zum Erstellen der POCO-Klassen und der Context-Klasse (enthält den Datenbank-Zugriff) werden 2 T4-Templates benutzt: z.B. DataModel.tt und DataModel.Context.tt
Durch Ändern dieser Dateien kann die Code-Generierung verändert werden.

Das Extrahieren der Dokumentation aus dem EDMX-Modell ist sehr einfach, leider aber nicht gut dokumentiert. Jedes MetaitemData-Objekt (z.B. der EntityContairner, jedes EntitySet oder jeder EntityType) enthält ein optionales Property 'Documentation'. Hier sind 'Summary' und 'LongDescription' aus dem Modell abgelegt.

folgende Punkte sind zu beachten:

  1. ist keine Dokumentation im Modell hinterlegt, ist .Documentation null
  2. Zeilenumbrüche müssen beim Erstellen der XML-Kommentare entsprechend um den Komentar-Prefix ergänzt werden
  3. die Dokumentation muss XML-Encoded werden (z.B. &, <, >)

Als C#-Beispiel wurden die T4-Templates um folgenden Code ergänzt:

      
      #region XML-Comments
        private const string XMLCOMMENT_START = "/// ";
        
        private static string XmlEntityize(string text)
        {
          if (string.IsNullOrEmpty(text))
          {
            return string.Empty;
          }
        
          text = text.Replace("&","&amp;");
          text = text.Replace("<","&lt;").Replace(">","&gt;");
          string id = Guid.NewGuid().ToString();
          text = text.Replace(Environment.NewLine, id);
          text = text.Replace("r""&#xD;").Replace("n","&#xA;");
          text = text.Replace(id, Environment.NewLine);
          return text.Replace("'","&apos;").Replace(""","&quot;");
        }
        private static string PrefixLinesOfMultilineComment(string prefix, string comment)
        {
          return comment.Replace(Environment.NewLine, Environment.NewLine + prefix);
        }
        
        public static string SummaryCommentElement(MetadataItem item, string defaultComment)
        {
          var comment = ((item.Documentation != null) && !string.IsNullOrWhiteSpace(item.Documentation.Summary))
                       ? item.Documentation.Summary : defaultComment;
          if (string.IsNullOrWhiteSpace(comment))
            return string.Empty;
        
          comment = PrefixLinesOfMultilineComment(XMLCOMMENT_START, XmlEntityize(comment));
          return string.Format((comment.Contains(Environment.NewLine)
                       ? "{0}<summary>n{0}{1}n{0}</summary>" : "{0}<summary>{1}</summary>"),
                               XMLCOMMENT_START, comment);
        }

        public static string LongDescriptionCommentElement(MetadataItem item, int indentLevel)
        {
        var comment = ((item.Documentation != null) &&
                        !string.IsNullOrWhiteSpace(item.Documentation.LongDescription))
                        ? item.Documentation.LongDescription : string.Empty;
          if (string.IsNullOrWhiteSpace(comment))
            return string.Empty;
          
          comment = PrefixLinesOfMultilineComment(XMLCOMMENT_START, XmlEntityize(comment));
          return string.Format((comment.Contains(Environment.NewLine)
                       ? "n{0}<LongDescription>n{0}{1}n{0}</LongDescription>"
                               : "n{0}<LongDescription>{1}</LongDescription>"),
                               XMLCOMMENT_START, comment);
        }

        public static string ParameterComments(IEnumerable<Tuple<stringstring>> parameters, int indentLevel)
        {
          System.Text.StringBuilder builder = new System.Text.StringBuilder();
          foreach (Tuple<stringstring> parameter in parameters)
          {
            builder.AppendLine();
            builder.Append(CodeRegion.GetIndent(indentLevel));
            builder.Append(XMLCOMMENT_START);
            builder.Append(String.Format(CultureInfo.InvariantCulture,
                                " <param name="{0}">{1}</param>", parameter.Item1, parameter.Item2));
          }
          return builder.ToString();
      }
      #endregion // XML-Comments

Verwendet wird das dann z.B. so:

      <#=SummaryCommentElement(entity, "Generated Entity-Class.")#> <#=LongDescriptionCommentElement(entity, region.CurrentIndentLevel)#>
      

Ist doch cool, oder?