C# EntityFramework是否按ID获取对象?

C# EntityFramework是否按ID获取对象?,c#,asp.net,linq,entity-framework,reflection,C#,Asp.net,Linq,Entity Framework,Reflection,使用泛型是否可以在不知道类型的情况下从EntityFramework获取对象 我在想一些大致如下的事情: public T GetObjectByID<T>(int id) { return (from i in myDatabase.T where i.ID == id select i); } public T GetObjectByID(int-id) { 返回(来自myDatabase.T中的i,其中i.ID==ID选择i); } 这可行吗?我可以使用反射以某种方式

使用泛型是否可以在不知道类型的情况下从EntityFramework获取对象

我在想一些大致如下的事情:

public T GetObjectByID<T>(int id)
{
   return (from i in myDatabase.T where i.ID == id select i);
}
public T GetObjectByID(int-id)
{
返回(来自myDatabase.T中的i,其中i.ID==ID选择i);
}
这可行吗?我可以使用反射以某种方式获取
T.GetType().Name
并将其用于表吗

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

我认为
Find()
方法可能能够完成您要查找的内容()


您可以定义由所有实体实现的接口:

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);
}
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);         
}
public T GetObjectById(int-id),其中T:class,IEntity
{
返回context.CreateObjectSet().SingleOrDefault(e=>e.Id==Id);
}
您还可以使用中提供的类似方法。您只需使用另一种方法来获取实体:

public T GetObjectById<T>(int id) where T : class, IEntity
{
    return context.CreateObjectSet<T>().SingleOrDefault(e => e.Id == id);
}
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);         
}
public virtual T GetByKey(int-id),其中T:class,icity
{
字符串containerName=context.DefaultContainerName;
字符串setName=context.CreateObjectSet().EntitySet.Name;
//生成实体密钥
var entityKey=新的entityKey(containerName+“+”集合名,“Id”,Id);
return(TEntity)Context.GetObjectByKey(entityKey);
}
区别在于,第一种方法总是查询数据库,即使您已经将实例加载到上下文中,而第二种方法首先检查实例是否已经加载。该方法效率不高,因为它反复构建这些名称。是一种更通用的方法,可以处理任何键类型和名称,也是一种处理复杂键的方法


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

最终解决了这个问题:

要调用代码,我使用以下命令:

// 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);
//获取要保存的对象的id
PropertyInfo prop=GetProperty(实体,实体.EntityKey.EntityKeyValues[0].Key);
字符串entityID=prop.GetValue(entity,null).ToString();
//获取此对象的当前版本
var originalEntity=GetEntity(PropertyEquals,entityID);

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

很难制定一个完全通用的解决方案,因为实体可以有复合键,但这适用于简单的单键情况

关键是将
T
限制为
System.Data.Objects.DataClasses.EntityObject
类型,然后该类型具有as
EntityKey
属性(表示主键)

静态T GetById(对象id),其中T:EntityObject
{
使用(var context=new myenties())
{
返回context.CreateObjectSet()
.SingleOrDefault(t=>t.EntityKey.EntityKeyValues[0].Value==id);
}
}

以下是我用来通过ID获取实体对象的方法

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);
    }
public tenty GetByKey(object keyValue),其中tenty:class
{            
EntityKey=GetEntityKey(keyValue);
对象源项;
if(ObjectContext.TryGetObjectByKey(key,out originalItem))
{
返回(强度)初始值;
}
返回默认值(tenty);
}

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

我想这可能会有帮助

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();
      }
    }
公共静态TEntity Find(此对象集,对象id),其中TEntity:EntityObject
{
使用(var context=new MyObjectContext())
{
var entity=set.Context.CreateObjectSet();
string keyName=entity.FirstOrDefault().EntityKey.EntityKeyValues.FirstOrDefault().Key;
返回实体.Where(“it.+keyName+”=“+id).FirstOrDefault();
}
}

从实体框架上的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();
}

我所做的一件工作是定义一个“KeyComparator”接口:

public interface IHasKeyComparator<TObject> {
   Expression<Func<TObject, bool>> KeyComparator { get; } 
}
公共接口IHasKeyComparator{
表达式键比较器{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;
   }
}
公共密封类多键对象:IHasKeyComparator{
公共int ID1{get;set;}
公共字符串ID2{get;set;}
只读表达式比较器;
公共表达式密钥比较器{
获取{return mKeyComparator;}
}
公共多键对象(){
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);
}
公共TObject刷新(TObject对象)
何处为对象:IHasKeyComparator{
返回此.Set().Single(POObject.KeyComparator);
}

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

我使用的是ObjectContext和EntityObjects。我希望我有。查找,但我没有。这还需要我提供主键的字符串名称。所以基本上我认为这是行不通的。我有一个相关的问题可能会帮到你。你在这个问题上的答案使用DbContext,我们使用ObjectContextThis可以帮助你:在这种情况下,t不一定是实体类型。它可以是超类型,例如,
System.Object
,也可以是代理子类型。您的签名中没有提供足够的信息来解决所有情况下的问题。链接也有同样的问题,它使用MVC/DBSET,而我使用的是ObjectContext。您的第二种方法可能适合我,但它假设我的ID列在整个数据库中是一致的(事实并非如此)。实际上,我非常接近于一种不会做出这种假设的方法。将泛型类型限制为扩展
EntityObject的类型可能会给您带来一些好处<
public TObject Refresh<TObject>(TObject pObject)
where TObject : IHasKeyComparator<TObject> {
   return this.Set<TObject>().Single(pObject.KeyComparator);
}