【问题标题】:EntityFramework - Detect DatabaseGenerated propertiesEntityFramework - 检测数据库生成的属性
【发布时间】:2013-08-14 16:59:10
【问题描述】:

我正在使用 EntityFramework - Code First,带有 POCO 类的 DBContext。

在运行时,我如何检测属性属于在数据库中生成的字段,标记为 .HasDatabaseGeneratedOption 、 .IsRowVersion(只读?)等。

我看了var xxx = Entity.GetType().GetProperty("ID").Get... ,没有运气。

public partial class OnMuhasebeContext : DbContext
{   

    public bool IsDatabaseGeneratedProperty <?>(...)
    {
        // Parameters : 
        // We know all poco classes of course
        // also parameters can be instance type
    }
}

更新:
请将“数据库生成”阅读为“由数据库生成值的字段”并在模型中标记以反映这一点。 这些属性都属于数据库生成的字段,并使用 Fluent API 标记为身份和 RowVersion。

public class POCOMap : EntityTypeConfiguration<POCO>
{
    public POCOMap()
    {
        // Primary Key
        this.HasKey(t => t.ID);

        this.Property(t => t.RowVersion)
            .IsFixedLength()
            .HasMaxLength(8)
            .IsRowVersion();
     }
 }

重点:如何在模型或代码优先模型中获取属性,使用 Fluent API 或 Data Annotions。数据库本身并不重要,就像实体框架背后的哲学一样。

【问题讨论】:

  • 嗯,你说你使用的是 Code First。你怎么会有数据库生成的属性?或者你的意思是你有数据库需要的字段?
  • 请查看更新部分。 RowVersion-Timestamp 字段的值由数据库在更新时设置。自动增量标识字段值由数据库在插入时给出。

标签: c#


【解决方案1】:

好吧,我想我明白了你想要达到的目标。

遗憾的是,您无法开箱即用地访问 EntityTypeConfiguration。 但是,您还可以做其他事情。您可以使用自己的 Attribute 并将其放在具有数据库生成值的属性上。

一个例子:

我们的自定义属性:

[AttributeUsage(AttributeTargets.Property)]
public class GeneratedByDatabaseAttribute : Attribute
{

}

一个非常简单的使用属性的poco:

public class SimplePoco
{
    [GeneratedByDatabase]
    public int Id { get; set; }

    [GeneratedByDatabase]
    public int RowVersion { get; set; }

    public string Name { get; set; }
}

这就是魔法发生的地方。我正在使用 GetPropertyInfo 从 lambda 表达式中获取成员。到目前为止,这种方法是不完整的,但是在 stackoverflow 周围有足够的样本。 简而言之:我得到了给定属性的 PropertyInfo 并检查它是否具有我们的自定义 GeneratedByDatabaseAttribute 属性。

public class MyContext : DbContext
{
    public bool IsDatabaseGeneratedProperty<TSource>(Expression<Func<TSource, object>> propertyExpression)
    {
        var property = GetPropertyInfo(propertyExpression);
        var attribute = property.GetCustomAttribute<GeneratedByDatabaseAttribute>();
        return attribute != null;
    }

    public PropertyInfo GetPropertyInfo<TSource>(Expression<Func<TSource, object>> propertyLambda)
    {
        var member = propertyLambda.Body as MemberExpression;
        if (member == null)
        {
            var ubody = (UnaryExpression)propertyLambda.Body;
            member = ubody.Operand as MemberExpression;
        }
        return member.Member as PropertyInfo;
    }
}

这是我用 LinqPad 测试它的方式:

void Main()
{
    var context = new MyContext();
    var result = context.IsDatabaseGeneratedProperty<SimplePoco>(poco => poco.Id);
    // result: True
    Console.WriteLine(result);

    result = context.IsDatabaseGeneratedProperty<SimplePoco>(poco => poco.Name);
    // result: False
    Console.WriteLine(result);
}

【讨论】:

  • 绝对运行良好的代码。非常感谢。你给出了精彩的解释,我快速运行示例项目,非常感谢。 (系统暂时不允许我投票,但我会投票)
  • 基于 FluentApi 的映射已经存在于 entityframework 模型中,如果可能的话我想使用它。我可以使用这种方法从实体框架模型或类中获取信息吗?我正在寻找 entityframework 源代码来理解它。
  • 恐怕不行。使用我的解决方案仍然是一个通用解决方案,您可以将其应用于整个应用程序。旁注:您应该能够接受答案。 Entity Frameworks 在其 codeplex 网站上免费提供。
  • 乔迪·兰根,非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-21
  • 1970-01-01
相关资源
最近更新 更多