Priya-Kiko Ответов: 1

Как получить атрибут [key] в сгенерированном коде codedom


Привет,

У меня есть этот код для генерации класса.

namespace EFCodeFirstTest
{
    class GenClass
    {
        CodeCompileUnit CompileUnit;
        CodeTypeDeclaration NewClass;

        public GenClass(String Classname)
        {
            CompileUnit = new CodeCompileUnit();
            CodeNamespace ns = new CodeNamespace("EFCodeFirstTest");
            ns.Imports.Add(new CodeNamespaceImport("System"));
            ns.Imports.Add(new CodeNamespaceImport("System.Collections.Generic"));
            ns.Imports.Add(new CodeNamespaceImport("System.ComponentModel.DataAnnotations"));
            ns.Imports.Add(new CodeNamespaceImport("System.ComponentModel.DataAnnotations.Schema"));
            ns.Imports.Add(new CodeNamespaceImport("System.Data.Entity.Spatial"));
            NewClass = new CodeTypeDeclaration(Classname);
            NewClass.IsClass = true;
            NewClass.TypeAttributes = TypeAttributes.Public | TypeAttributes.Sealed;
            ns.Types.Add(NewClass);
            CompileUnit.Namespaces.Add(ns);
        }

        public void AddColumns()
        {
            CodeMemberField mfield0 = new CodeMemberField(typeof(Int32), "RefNo");
            mfield0.Attributes = MemberAttributes.Public;
            mfield0.Type = new CodeTypeReference(typeof(Int32));
            NewClass.Members.Add(mfield0);
        }

        public void CreateCS(String mfilename)
        {
            CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
            CodeGeneratorOptions options = new CodeGeneratorOptions();
            options.BracingStyle = "C";
            options.BlankLinesBetweenMembers = false;
            using (StreamWriter sw = new StreamWriter(mfilename))
            {
                provider.GenerateCodeFromCompileUnit(CompileUnit, sw, options);
            }
        }
    }
}



Я называю это так :

GenClass objGenClass = new GenClass("Folio2");
objGenClass.AddColumns();
objGenClass.CreateCS(@"../../Models/Folio2.cs");


Он сгенерировал этот код :

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.42000
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace EFCodeFirstTest
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    using System.Data.Entity.Spatial;
    
    public sealed class Folio2
    {
        public int RefNo;
    }
}




Как я могу добавить атрибут [Key] над полем, а также как обозначить поле как IDENTITY ?

Я ищу этот выход :

[Key]
public int Refno {get; set;}

Пожалуйста, предложите. Заранее спасибо.

Что я уже пробовал:

Попробовал сделать это как в эта ссылка но это не работает для атрибута первичного ключа.

Попробовал добавить атрибут KeyAttribute через CustomAttributes.Add. Но это не сработало.

также пробовать :

CodeAttributeDeclaration mattr = new CodeAttributeDeclaration("Key");
CodeMemberField mfield0 = new CodeMemberField(typeof(Int32), "RefNo");
mfield0.CustomAttributes.Add(mattr);


Это привело к тому, что :

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.42000
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace EFCodeFirstTest
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    using System.Data.Entity.Spatial;
    
    public sealed class Folio2
    {
        [Key()]
        public int RefNo;
    }
}

Maciej Los

Насколько я помню, если вы замените RefNo с ID, EF будет рассматривать это поле как [ключ].

Priya-Kiko

Спасибо Вам за ответ. Попробовал изменить имя столбца на ID, но безуспешно !!

1 Ответов

Рейтинг:
2

Maciej Los

Кажется, вам нужно добавить ссылку на: System.ComponentModel.DataAnnotations, затем добавить CodeAttributeDeclaration. Видеть:

var attr = new CodeAttributeDeclaration(new CodeTypeReference(typeof(System.ComponentModel.DataAnnotations.KeyAttribute)));


Источник:
Добавление атрибута с помощью Codedom в C# - переполнение стека[^]
c# - добавление аннотаций данных в класс, созданный entity framework - переполнение стека[^]
Класс KeyAttribute (System.ComponentModel.DataAnnotations) | Майкрософт Документы[^]

Примечание: не тестировалось!


Priya-Kiko

Спасибо за ответ @Maciej Los. Я попробовал воспользоваться кодом, который вы предложили. Но выход примерно такой :

пространство имен EFCodeFirstTest
{
использование системы;
использование системы.Коллекции.Общий;
использование системы.ComponentModel.DataAnnotations;
использование системы.ComponentModel.DataAnnotations.Схема;
использование System.Data.Entity.Пространственный;

общественные запечатанного класса Folio2
{
[Система.ComponentModel.DataAnnotations.Атрибут KeyAttribute()]
public int RefNo;
}
}

Обеспечит ли это функциональность [ключа]?

Maciej Los

Проверить это.

Priya-Kiko

- Нет ! EF не распознает это как первичный ключ. Я получил эту ошибку во время миграции.

EFCodeFirstTest.Объектом типа runtimetype: : объектом типа runtimetype атрибутом entitytype '' нет ключа. Определить ключевые для этой атрибутом entitytype.

Maciej Los

Итак, попробуйте использовать: new CodeTypeReference(typeof("[Key]"))
Я новичок в этом деле, так что ... ..

Priya-Kiko

ладно ... никаких проблем... Это не сработает.

Maciej Los

Что о:
attr.Arguments.Add(new CodeAttributeArgument(new CodePrimitiveExpression("[Key()]")));

Priya-Kiko

Он возвращает такой код :

общественные запечатанного класса Folio2
{
[("Ключ()")]
public int RefNo;
}

Maciej Los

Так что, похоже, мы на правильном пути :)

Priya-Kiko

Я каким-то образом получил приведенный ниже код, сгенерированный use CodeSnippetMember.

пространство имен EFCodeFirstTest
{
использование системы;
использование системы.Коллекции.Общий;
использование системы.ComponentModel.DataAnnotations;
использование системы.ComponentModel.DataAnnotations.Схема;
использование System.Data.Entity.Пространственный;

общественные запечатанного класса Folio2
{
[Ключ]
public int RefNo { get; set; }
public int RecNo { get; set; }
}
}

Но EF, похоже, не распознает это как первичный ключ, и когда я пытаюсь выполнить миграцию, он сообщает об этой ошибке.

EFCodeFirstTest.Объектом типа runtimetype: : объектом типа runtimetype атрибутом entitytype '' нет ключа. Определить ключевые для этой атрибутом entitytype.