我有以下代码:
public interface IKeyed<TKey>
{
TKey Id { get; }
}
// This is the entity framework generated model. I have added the
// IKeyed<Guid> interface
public partial class Person : IKeyed<Guid>
{
public Guid Id { get; set; }
}
public class Repository<TKey, TEntity> : IKeyedRepository<TKey, TEntity>
where TEntity : class, IKeyed<TKey>
{
private readonly IObjectSet<TEntity> _objectSet;
public Repository(IOjectSet<TEntity> objectSet)
{
_objectSet = objectSet;
}
public TEntity FindBy(TKey id)
{
return _objectSet.FirstOrDefault(x => x.Id.Equals(id));
}
}以下是我所称的最新情况:
Db2Entities context = new Db2Entities(_connectionString); // This is the EF context
IObjectSet<Person> objectSet = context.CreateObjectSet<Person>();
IKeyedRepository<Guid, Person> repo = new Repository<Guid, Person>(objectSet);
Guid id = Guid.NewGuid();
Person person = repo.FindBy(id); // This throws the exception.上面的代码编译。当执行'FindBy‘方法时,我得到以下错误:
无法创建“闭包类型”类型的常量值。在此上下文中只支持原始类型(例如Int32、String和Guid)。
因为我的“Id”类型是一个Guid (所支持的原始类型之一),所以我应该可以将它推入工作状态。
有人知道这是否可能吗?
谢谢,
鲍勃
发布于 2011-05-21 09:18:17
不是这样的。您不能调用Equals,因为EF不知道如何将其转换为SQL。当您将表达式传递给FirstOrDefault时,必须始终只有可以转换为SQL的代码。也许可以通过手工构建表达式树来解决您的问题,但是我可以参考已经在堆栈溢出上讨论过的其他解决方案。
ObjectContext提供了名为GetObjectByKey的方法,这正是您要做的。问题是它需要EntityKey作为参数。这里有两个答案,展示了如何使用这种方法和如何获得EntityKey
在您的示例中,代码将不那么复杂,因为您知道密钥属性的名称,所以通常只需要如下所示:
public virtual TEntity FindBy(TKey id)
{
// Build entity key
var entityKey = new EntityKey(_entitySetName, "Id", key);
// Query first current state manager and if entity is not found query database!!!
return (TEntity)Context.GetObjectByKey(entityKey);
}这里的问题是您无法从entitySetName获得IObjectSet,所以您必须将它传递给存储库构造函数,或者必须传递ObjectSet。
如果您将来想要使用DbContext API (EFv4.1),而不是ObjectContext API,这将大大简化,因为DbSet提供了Find方法:
https://stackoverflow.com/questions/6077353
复制相似问题