Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# DbSet.FirstOrDefault()?_C#_Entity Framework_Entity Framework 4.1_Dbcontext - Fatal编程技术网

C# DbSet.FirstOrDefault()?

C# DbSet.FirstOrDefault()?,c#,entity-framework,entity-framework-4.1,dbcontext,C#,Entity Framework,Entity Framework 4.1,Dbcontext,我正试图这么做,但上面说我不能使用FirstOrDefault public static int GetId(this Context db, Type type, string name) { return db.Set(type).FirstOrDefault(x => x.Name == name).Id; } 错误为“System.Data.Entity.DbSet”不包含“FirstOrDefault”的定义,并且找不到接受“System.Data.Entity.Db

我正试图这么做,但上面说我不能使用FirstOrDefault

public static int GetId(this Context db, Type type, string name)
{
    return db.Set(type).FirstOrDefault(x => x.Name == name).Id;
}
错误为“System.Data.Entity.DbSet”不包含“FirstOrDefault”的定义,并且找不到接受“System.Data.Entity.DbSet”类型的第一个参数的扩展方法“FirstOrDefault”(是否缺少using指令或程序集引用?

然后我尝试了这个
Cast
方法,但出现了一个错误无法从非泛型的DbSet为“WindowStyle”类型的对象创建DbSet(顺便说一句
WindowStyle
继承自下面的
DomainEntity


试着把它倒过来一点,好吗

set.Where(x => x.Name == name).Select(o=>o.Id).FirstOrDefault(); set.Where(x=>x.Name==Name);
您的将返回一个空实体,然后尝试从中获取Id。

第一个构造不起作用,因为您使用的是非泛型DbSet,因此无法应用FirstOrDefault扩展方法,该方法仅适用于泛型DbSet。听起来您已经理解了这一点,因为您已经在尝试获取非泛型DbSet。使用Cast()方法得到的错误是由于您试图将DbSet强制转换为DbSet引起的。这是不允许的,因为如果允许的话,就有可能将不一致的成员添加到DbSet(类型为WindowsStyle以外的对象)。另一种说法是dbset不支持协方差,因为dbset允许添加

我想你必须找到另一种方法来做你想做的事。以这种方式混合LINQ和继承显然是有问题的。既然已经定义了一个基类型,并且只处理基类型上可用的属性,为什么不直接查询基类型呢

    public static int GetId(this Context db, string name)
    {
        return db.DomainEntities.FirstOrDefault(x => x.Name == name).Id;
    }

您可能担心不同类型之间的名称冲突,但您可能可以从这一点开始,查看派生类型关联,以验证所查看的类型是否正确。解决这个问题的一种方法是在DomainEntity定义中添加一个类型标志。

这里是我的一个想法,它似乎正在发挥作用

public static int GetId(this Context db, Type type, string name)
{
    var set = db.Set(type);
    foreach (dynamic entry in set)
        if (entry.Name == name)
            return entry.Id; 
}

问题就在这里。只允许数据库类型的
DbSet
类(例如
Cast()
),因此此方法不允许
Cast()
,并引发异常

相反,您希望使用
IQueryable.Cast()
扩展方法,该方法将简单地将数据转换为基类型。下面是一个例子:

var set = ((IQueryable)db.Set(type)).Cast<DomainEntity>();
return set.First(x => x.Name == name).Id;
var set=((IQueryable)db.set(type)).Cast();
返回set.First(x=>x.Name==Name).Id;

这个答案可能对您没有帮助,这取决于您调用此方法的“动态”情况,基本上,如果您在编译时是否知道类型。如果您知道,您可以编写一个通用方法:

public static class MyExtensions
{
    public static int? GetId<TEntity>(this Context db, string name)
        where TEntity : DomainEntity
    {
        return db.Set<TEntity>()
            .Where(x => x.Name == name)
            .Select(x => (int?)x.Id)
            .FirstOrDefault();
    }
}
并称之为:

int? id = db.GetId("abc", someType);
如果
someType
没有从
DomainEntity
继承,那么它将在运行时抛出异常。通用版本将在编译时对此进行检查。所以,如果你喜欢第一个版本的话。

也许你错过了

using System.Linq;

您的文件顶部是否有
using System.Linq
?DbSet继承IEnumerable,但LINQ函数都是扩展方法,如果没有using语句将无法使用。您的第二个错误(
Cast
)是编译时错误还是运行时错误?这会有很大的不同,很难从你的问题中推断。@Chris,是的,我做了。好问题。@Scott,它是运行时的,显示在我的浏览器中。如果您的对象为空,并且您尝试引用id:)Paul,谢谢。但是我在
DbContext
上没有
DbSet
。这就是我有问题的原因吗?我只是使用
DomainEntity
通过继承来组织其他类。我认为真正的问题是我不理解泛型。我尝试使用
MakeGenericType
,但它说
DbSet
不是泛型类型。DbSet将从数据库检索实体。因此,如果没有为DomainEntity实体提供单独的数据库表,这种方法将失败。首先使用DB,这是绝对可以做到的。听起来你是在先使用代码;我从来没有先用代码做过,但这应该是可能的。在任何情况下,您都需要一个DomainEntity数据库集。在数据库方面,可以通过使派生实体的主键也成为父实体id的外键来建模继承。我想我尝试了
Where
,但它与
FirstOrDefault
的问题相同。谢谢。这确实解决了一个问题(不正确地使用了
FirstOrDefault
),但它与问题无关。您应该能够在这里用
DomainEntity
替换
dynamic
,这将给您与我的答案几乎相同的答案。将一个完整的表加载到内存中(可能有一百万行)只有一个Id看起来很不酷。循环的开始将执行查询
set
,而不使用任何过滤器。远离这个解决方案。@Slauma,此外,他在迭代整个表后返回匹配:)后期编辑。如果我能在这里给你我所有的声誉,我会-这是我寻找的大约半年,我总是做错误的方法。Thx,你现在真的是我的上帝了。我忘了确认那个系统。Linq在使用中!默认情况下,它几乎总是在那里,我从未想过要检查它。
int? id = db.GetId<WindowStyle>("abc");
public static class MyExtensions
{
    public static int? GetId(this Context db, Type entityType, string name)
    {
        return ((IQueryable<DomainEntity>)db.Set(entityType))
            .Where(x => x.Name == name)
            .Select(x => (int?)x.Id)
            .FirstOrDefault();
    }
}
int? id = db.GetId("abc", someType);
using System.Linq;