将属性设置为主键

时间:2014-10-08 06:12:47

标签: c# asp.net asp.net-mvc

我正在试图弄清楚如何将属性设置为主键。我的意思是,我有一个POCO对象,我试图像这样定义一个键:

public class POCO
{
    [PrimaryKey]
    int Id;

    string Name;
    int Age;    
}

然后我试图像这样访问它:

public static object ReturnKeyValue(this POCO poco)
{
    return poco.[PrimaryKey]; //should return Id 
}

我在这里做错了什么?

2 个答案:

答案 0 :(得分:1)

可以使用getter和setter将POCO类的PrimaryKey属性公之于众吗?

public class POCO
{
    [PrimaryKey]
    public int Id { get; set; }

    string Name;
    int Age;
}

如果是这样,那么以下扩展方法应该为任何给定的POCO实例返回PrimaryKey字段的值。

public static object ReturnKeyValue(this POCO poco)
{
    return (from p in poco.GetType().GetProperties()
            let attr = p.GetCustomAttributes(typeof(PrimaryKeyAttribute), true)
            where attr.Length == 1
            select p).First().GetValue(poco, null);
}

答案 1 :(得分:0)

我有类似的东西,我昨天找到了解决方案,所以我很乐意分享它。 您需要知道的是,当您拥有复合键时,您尝试执行的操作将永远不会起作用,这意味着,POCO对象具有一个主键,该主键可以包含多个单个元素。

假设我有以下课程(POCO):

public class Person : EntityBase<int>
{
    #region Properties

    /// <summary>
    ///     Gets or sets the id of the entity.
    /// </summary>
    [Key]
    public TKey Id { get; set; }

    /// <summary>
    ///     Gets or sets the name.
    /// </summary>
    public string Name { get; set; }

    /// <summary>
    ///     Gets or sets the firstname.
    /// </summary>
    public string FirstName { get; set; }

    /// <summary>
    ///     Gets or sets the <see cref="Manager"/>.
    /// </summary>
    public Manager Manager { get; set; }

    #endregion
}

我在这里使用Entity Framework,因此定义主键的属性称为Key而不是PrimaryKey,如您的示例所示。

现在,我确实有一个充当存储库的类。该类在对象中保存Person的所有对象,在我的测试场景中,它将这些对象保存在HashSet中:

private readonly HashSet<TEntity> _entitiesCollection = new HashSet<TEntity>();

TEntity实体所在的Person

此外,这个类确实有一个List<PropertyInfo>' object, named _ keyProperties`,它将保存该对象的所有键。

现在,我确实有一个方法可以找到充当给定对象的键的所有属性:

 private void GetKeyProperties()
 {
     _keyProperties = new List<PropertyInfo>();
     var properties = typeof(TEntity).GetProperties();

     foreach (var property in from property in properties from attribute in property.GetCustomAttributes(true).OfType<KeyAttribute>() select property)
     { _keyProperties.Add(property); }
 }

不,您可以选择与主键匹配给定值的所有内容。这可以通过以下方法实现:

protected virtual TEntity Find(params object[] keyValues)
{
    if (keyValues.Length != _keyProperties.Count) throw new ArgumentException("Incorrect number of keys passed to find method");

    var keyQuery = this.AsQueryable();
    keyQuery = keyValues.Select((t, i) => i).Aggregate(keyQuery, (current, x) => current.Where(entity => _keyProperties[x].GetValue(entity, null).Equals(keyValues[x])));

    return keyQuery.SingleOrDefault();
}

或者,例如,如果要执行实体更新,可以执行以下操作:

public void Update(TEntity entity)
{
    // First the original entity is retrieve by searching the key, this item is then removed from the collection
    // Then a new item is being added to the collection.
    var original = Find(_keyProperties.Select(e => e.GetValue(entity)).ToArray());
    Detach(original);

    _entitiesCollection.Add(entity);
}

这样做是基于主键搜索原始实体,删除该实体,然后再次添加更新的实体。

所以,我希望这会有所帮助。