EntityFramework按ID获取对象?

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

我正在考虑以下方面的事情:

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

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

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

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

 public interface IEntity { int Id { get; } } 

和检索实体的方法:

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

您也可以使用与链接问题中提供的方法类似的方法。 您只需使用另一种方法来获取您的实体:

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

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

这种方法都不能直接用于inheritance – 您必须提供基本类型才能使其工作。

我认为Find()方法可能能够做你想要的( DbSet.Find方法 )。

 var someEntity = dbSet.Find(keyValue); 

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

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

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

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

要调用代码我使用:

 // Get the id of the object we are saving PropertyInfo prop = GetProperty(entity, entity.EntityKey.EntityKeyValues[0].Key); string entityID = prop.GetValue(entity, null).ToString(); // Get the current version of this object var originalEntity = GetEntity(PropertyEquals, entityID); 

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

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

 public T Get(int id) where T : EntityObject; { var ObjectSet = _context.CreateObjectSet(); 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 

我认为这可能会有所帮助

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

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

 public interface IHasKeyComparator { Expression> KeyComparator { get; } } 

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

 public sealed class MultiKeyedObject : IHasKeyComparator { public int ID1 { get; set; } public string ID2 { get; set; } readonly Expression> mKeyComparator; public Expression> KeyComparator { get { return mKeyComparator; } } public MultiKeyedObject() { mKeyComparator = other => other.ID1 == ID1 && other.ID2 == ID2; } } 

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

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

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

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

 public TEntity GetByKey(object keyValue) where TEntity : class { EntityKey key = GetEntityKey(keyValue); object originalItem; if (ObjectContext.TryGetObjectByKey(key, out originalItem)) { return (TEntity)originalItem; } return default(TEntity); } 

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