在EF Code First中,是否有一个用于描述字段的数据注释?

4
在设计MS-SQL表时,您可以选择为添加到表中的每个列添加描述。在使用Data AnnotationsEF Code First中是否可以实现同样的功能呢?

你需要像这样写 [Description("这里是属性描述")] public int PropName {get;set;} 来创建一个额外的EF列在数据库中,但它是不可见的吗? - Bassam Alugili
@BassamAlugili:数据注释是这样的,但它会在数据库中生成描述吗? - Afshar Mohebi
1个回答

0
在使用我的解决方案之前,请先了解一些相关内容:
扩展属性: https://technet.microsoft.com/en-us/library/ms190243(v=sql.105).aspx

Attributes:
http://www.dotnetperls.com/attribute

我的解决方案将允许您为任何属性进行阴影描述,例如:

[Description("My Column description!")]
public string RegionCity { get; set; }

注意事项:

  • 复制粘贴解决方案,一切都应该正常工作(不要忘记app.config连接字符串)!
  • 您可以使用sql命令IF NOT EXISTS来检查扩展属性是否已经存在。
  • 您可以构建自己的通用逻辑或C#扩展来读取任何属性的描述,这应该很容易,只需添加一个字符串示例即可。

    using System;
    using System.Linq;
    
    namespace EntityFrameworkDemo
    {
     using System.Data.Entity;
    
    public class Program
    {
        public static void Main()
        {
            Database.SetInitializer(new DropCreateDatabaseAlways<MyDbContext>());
    
    
            using (var myDbContext = new MyDbContext("DefaultConnection"))
            {
                // 可能您不需要此行!
                myDbContext.Database.Initialize(true);
    
                // 添加一次或使用IF NOT EXISTS SQL命令!
                var c = new ColumnsDescription();
                c.AddColumnsDescriptions(myDbContext);
    
                var region = new Region { RegionCity = "测试1", RegionSeconcdCity = "测试2" };
                myDbContext.Regions.Add(region);
                myDbContext.SaveChanges();
            }
    
    
            // 读取扩展属性
            using (var myDbContext = new MyDbContext("DefaultConnection"))
            {
                var ep = "select value from fn_listextendedproperty('MS_Description','schema','dbo','table', 'Regions', 'column', 'RegionCity');";
    
                // 例如,您可以像以下方式读取扩展属性,或者您可以创建一个通用的读取器
                var properties = myDbContext.Database.SqlQuery<string>(ep).First();
    
                Console.WriteLine(properties);
            }
        }
    
        [AttributeUsage(AttributeTargets.Property)]
        public class DescriptionAttribute : Attribute
        {
            string value;
    
            public DescriptionAttribute(string id)
            {
                this.value = id;
            }
    
            public string Value
            {
                get { return this.value; }
            }
        }
    
        public class ColumnsDescription
        {
            public void AddColumnsDescriptions(DbContext mydbContext)
            {
                // 获取包含您的属性的DbContext类公共属性
                var dbContextProperies = typeof(DbContext).GetProperties().Select(pi => pi.Name).ToList();
    
                // 循环每个类型为T的DbSets
                foreach (var item in typeof(MyDbContext).GetProperties()
                    .Where(p => dbContextProperies.IndexOf(p.Name) < 0)
                    .Select(p => p))
                {
                    if (!item.PropertyType.GetGenericArguments().Any())
                    {
                        continue;
                    }
    
                    // 获取“T”的类型
                    var entityModelType = item.PropertyType.GetGenericArguments()[0];
                    var descriptionInfos = from prop in entityModelType.GetProperties()
                                           where prop.GetCustomAttributes(typeof(DescriptionAttribute), true).Any()
                                           select new { ColumnName = prop.Name, Attributes = prop.CustomAttributes };
    
                    foreach (var descriptionInfo in descriptionInfos)
                    {
                        // Sql创建描述列并添加
                        var addDiscriptionColumnSql =
                            @"sp_addextendedproperty  @name = N'MS_Description', @value = '"
                            + descriptionInfo.Attributes.First().ConstructorArguments.First()
                            + @"', @level0type = N'Schema', @level0name = dbo,  @level1type = N'Table',  @level1name = "
                            + entityModelType.Name + "s" + ", @level2type = N'Column', @level2name ="
                            + descriptionInfo.ColumnName;
    
                        var sqlCommandResult = mydbContext.Database.ExecuteSqlCommand(addDiscriptionColumnSql);
                    }
                }
            }
        }
    
        public class Region
        {
            public int Id { get; set; }
    
            [Description("我的列描述!")]
            public string RegionCity { get; set; }
    
            [Description("我的第二列描述!")]
            public string RegionSeconcdCity { get; set; }
    
        }
    
        public class MyDbContext : DbContext
        {
            public DbSet<Region> Regions { get; set; }
    
            public MyDbContext(string connectionString)
                : base("name=" + connectionString)
            {
            }
        }
    }
    }   
    

谢谢你的解决方案。但对于我的需求来说有点复杂。我无法理解它。希望实体类只需要一个“属性”,就可以将描述添加到数据库中。 - Afshar Mohebi
@afsharm 这个属性在 EF 中不存在,你必须自己创建它。对于这个问题,没有一个神奇的一行代码的简单解决方案。看看那些开发者,他们有同样的问题,并且通过迁移解决了这个问题,这比我的解决方案要复杂得多。https://dev59.com/PGkw5IYBdhLWcg3wKnib - Bassam Alugili
@afsharm 如果您需要更多的澄清,我很乐意帮助您! - Bassam Alugili

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接