EntityFramework按ID获取对象?

时间:2011-05-27 18:54:46

标签: c# asp.net linq entity-framework reflection

Generics是否可以在不知道类型的情况下从我的EntityFramework中获取对象?

我正在考虑以下几点:

public T GetObjectByID<T>(int id)
{
   return (from i in myDatabase.T where i.ID == id select i);
}

可行吗?我可以使用Reflection以某种方式获取T.GetType().Name并将其用于表吗?

修改
另一个问题是,并非所有可用的表都使用“ID”作为其唯一的列名。

8 个答案:

答案 0 :(得分:30)

您可以定义所有实体实施的界面:

public interface IEntity
{
    int Id { get; }
}

以及检索实体的方法:

public T GetObjectById<T>(int id) where T : class, IEntity
{
    return context.CreateObjectSet<T>().SingleOrDefault(e => e.Id == id);
}

您也可以使用与linked question中提供的方法类似的方法。您只需使用其他方法来获取您的实体:

public virtual T GetByKey<T>(int id) where T : class, IEntity
{
     string containerName = context.DefaultContainerName;
     string setName = context.CreateObjectSet<T>().EntitySet.Name;
     // Build entity key
     var entityKey = new EntityKey(containerName + "." + setName, "Id", id);
     return (TEntity)Context.GetObjectByKey(entityKey);         
}

不同之处在于,即使您已将实例加载到上下文,第一种方法也始终查询数据库,而第二种方法首先检查实例是否已加载。该方法效率不高,因为它反复构建这些名称。 Here是更通用的方法,可以使用任何键类型和名称,here是使用复杂键的方法。

这两种方法都不能直接用于继承 - 你必须提供基类型才能使它工作。

答案 1 :(得分:23)

我认为Find()方法可以做你想要的事情(DbSet.Find Method)。

var someEntity = dbSet.Find(keyValue);

答案 2 :(得分:5)

很难制作完全通用的解决方案,因为实体可以使用复合键,但这适用于简单的单键案例。

关键是要将T限制为System.Data.Objects.DataClasses.EntityObject类型,然后将其作为EntityKey属性(代表主键)。

static T GetById<T>(object id) where T : EntityObject
{
    using (var context = new MyEntities())
    {
        return context.CreateObjectSet<T>()
            .SingleOrDefault(t => t.EntityKey.EntityKeyValues[0].Value == id);
    }
}

答案 3 :(得分:3)

最后解决了这个问题:
http://pastebin.com/kjXUKBNS

要调用代码我使用:

// Get the id of the object we are saving
PropertyInfo prop = GetProperty<TEntity>(entity, entity.EntityKey.EntityKeyValues[0].Key);
string entityID = prop.GetValue(entity, null).ToString();

// Get the current version of this object
var originalEntity = GetEntity<TEntity>(PropertyEquals, entityID);

这假设您正在搜索的主键是主键列表中的第一个。

答案 4 :(得分:3)

从实体框架上的id获取实体的另一种方法

public T Get<T>(int id) where T : EntityObject;
{
var ObjectSet = _context.CreateObjectSet<T>();
var PropName = ObjectSet.EntitySet.ElementType.KeyMembers[0].ToString();
return  ObjectSet.Where("it." + PropName + "=" + id).FirstOrDefault();
}

<强>结果

SELECT TOP (1) 
[Extent1].[CatId] AS [CatId], 
[Extent1].[CatName] AS [CatName], 
[Extent1].[CatType] AS [CatType],  
FROM [dbo].[Categories] AS [Extent1]
WHERE [Extent1].[CatId] = 1

答案 5 :(得分:2)

我认为这可能会有所帮助

public static TEntity Find<TEntity>(this ObjectSet<TEntity> set, object id) where TEntity : EntityObject
    {
      using (var context = new MyObjectContext())
      {
        var entity = set.Context.CreateObjectSet<TEntity>();
        string keyName = entity.FirstOrDefault().EntityKey.EntityKeyValues.FirstOrDefault().Key;

        return entity.Where("it." + keyName + " = " + id).FirstOrDefault();
      }
    }

答案 6 :(得分:0)

我做过的一件事就是定义一个“KeyComparator”界面:

public interface IHasKeyComparator<TObject> {
   Expression<Func<TObject, bool>> KeyComparator { get; } 
}

然后,即使使用多值键,您也可以在某个对象上实现它:

public sealed class MultiKeyedObject : IHasKeyComparator<MultiKeyedObject> {
   public int ID1 { get; set; }
   public string ID2 { get; set; }       

   readonly Expression<Func<MultiKeyedObject, bool>> mKeyComparator;

   public Expression<Func<MultiKeyedObject, bool>> KeyComparator {
      get { return mKeyComparator; }
   }

   public MultiKeyedObject() {
      mKeyComparator = other => other.ID1 == ID1 && other.ID2 == ID2;
   }
}

如果你提供约束,可以一般使用它:

public TObject Refresh<TObject>(TObject pObject)
where TObject : IHasKeyComparator<TObject> {
   return this.Set<TObject>().Single(pObject.KeyComparator);
}

这样做需要您拥有该对象的实例,尽管您可以使用键值填充空的实例,然后使用它从数据库中提取。

答案 7 :(得分:-1)

这是我用来通过ID获取Entity对象的方法。

public TEntity GetByKey<TEntity>(object keyValue) where TEntity : class
    {            
        EntityKey key = GetEntityKey<TEntity>(keyValue);

        object originalItem;
        if (ObjectContext.TryGetObjectByKey(key, out originalItem))
        {
            return (TEntity)originalItem;
        }
        return default(TEntity);
    }

您可能会发现这是一个比上面提供的更强大的解决方案。我在很多项目中都将它用作通用存储库的一部分。希望它可以帮助你。