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
Entity framework 为什么在使用EF的上下文中只支持基元类型或枚举类型?_Entity Framework_Linq_Join_Entity Framework 6_Repository Pattern - Fatal编程技术网

Entity framework 为什么在使用EF的上下文中只支持基元类型或枚举类型?

Entity framework 为什么在使用EF的上下文中只支持基元类型或枚举类型?,entity-framework,linq,join,entity-framework-6,repository-pattern,Entity Framework,Linq,Join,Entity Framework 6,Repository Pattern,在我的应用程序中,我尝试使用EntityFramework、Repository模式执行一个连接查询,它抛出了下面的错误。链接查询中有什么问题?让我详细解释一下 错误描述 无法创建“匿名类型”类型的常量值。只有 在此上下文中支持基元类型或枚举类型 初始化 主查询[不工作] 尝试实现下面的SQL查询 奇怪的发现 如果我包括托利斯;对于每个查询,如来自we in _repository.GetAll.ToList的查询,整个查询都将正常工作并给出预期结果,不会出现任何错误 所以,如果我将每个查询返回

在我的应用程序中,我尝试使用EntityFramework、Repository模式执行一个连接查询,它抛出了下面的错误。链接查询中有什么问题?让我详细解释一下

错误描述

无法创建“匿名类型”类型的常量值。只有 在此上下文中支持基元类型或枚举类型

初始化

主查询[不工作]

尝试实现下面的SQL查询

奇怪的发现

如果我包括托利斯;对于每个查询,如来自we in _repository.GetAll.ToList的查询,整个查询都将正常工作并给出预期结果,不会出现任何错误

所以,如果我将每个查询返回类型转换为内存中的或IEnumerable,它将按预期工作,没有任何错误,但IQueryable查询未按预期工作

新代码段[正在运行]


在您的情况下,无法将数据库表与内存中的集合联接,请列出:

通过调用ToList将这些集合转换为内存中的集合:

然后尝试加入下一段代码

如果您只是删除那些ToList调用,那么连接应该可以工作。如果您愿意,您可以保留用于最终结果的连接

请记住,IEnumerable是惰性的,只有通过foreach循环或ToList之类的函数进行迭代来执行SQL查询,IEnumerable才会真正运行SQL查询。

让我解释一下

您有一个GenericRepository类,类似这样:

public class GenericRepository<T>
{
    MyDbContext dbContext;
    public GenericRepository()
    {
        dbContext = new MyDbContext();
    }
    public IQueryable<T> GetAll()
    {
        // whatever
    }
}
您正在加入IQueryable,其中包含内存中的列表。运行此查询时,EF无法知道内存中的列表组和组成员实际上是来自数据库的查询。它只看到两个列表,其中包含一些数据。它无法将其转换为SQL,因此会抛出一个错误

要解决此问题,您应该删除对ToList的调用。这样,您就有了三个连接在一起的iQueryTable。EF可以将其转换为SQL,前提是它们来自单个DbContext。既然它们不是,它就会抛出另一个错误,确切地告诉你这一点

为每个GenericRepository实例创建实例DbContext。所以,组、组成员和我们来自三个不同的背景

为了解决这个错误,您应该设法为所有GenericRepository使用一个DbContext

例如:

using (var dbContext = new MyDbContext())
{
    var groups = dbContext.Set<Group>();
    var groupMembers = dbContext.Set<GroupMember>();

    var results = from we in dbContext.Set<WeeklyEntry>()
                  join g in groups
                  on we.GroupID equals g.ID into grpjoin
                  ...

}

你可以发布_repository.GetAll的签名吗?@sam:已经在发布中了_repository=new genericreepository;iQueryEnable如果我删除ToList,它将通过另一个错误显示,指定的LINQ表达式包含对与不同上下文关联的查询的引用听起来像是在存储库类中使用多个上下文对象。如果查看GenericRepository的构造函数,每次都可能创建一个新上下文。相反,请通过构造函数传递上下文,并在存储库中使用相同的上下文。@ShubhajyotiGhosh use a DI framework ASP.NET Core有一个内置的,并按范围添加数据上下文。@Mohammaddehgan:Project不包含任何DI,因此无法在此处使用它。你觉得这是因为检查!!!如果我们使用'DI',我们永远不会面对这个问题???@ShubhajyotiGhosh,正如oofmycode所说,您的第二个错误来自于您在每个存储库中创建一个新的DataContext,因此,您无法加入来自不同存储库的查询。您可以清楚地看到这个错误。因为您要从存储库返回普通iQueryable,所以使用它们不会带来任何好处。摆脱它们,直接使用DataContext。我得到了你的piint,在这里我无法使用任何DI,所以我可以做一件事,在存储库中更改一点来解决错误。没有“ToList”实现。顺便说一句,现在查询可以使用“ToList”生成正确的结果数据库中存在关系问题,这就是我出错的原因。调用ToList会将您的全部数据放入内存,并在内存中运行所有连接。这破坏了使用关系数据库的全部意义!
 var results = (from we in _repository.GetAll()
                join g in groups on we.GroupID equals g.ID into grpjoin
                from g in grpjoin.DefaultIfEmpty()
                join gm in groupMembers on we.DepositedByMemberID equals gm.ID into gmjoin
                from gm in gmjoin.DefaultIfEmpty()
                where gm.GroupID == g.ID
                select new
                {
                     GroupID = g.ID,
                     GroupName = g.Name,
                     MemberID = grpmresult.ID,
                     grpmresult.Name,
                     we.ID                                  
                 }).ToList();
select w.GroupID, g.Name, gm.Name, w.ID
from [dbo].[WeeklyEntry] as w
left outer join [dbo].[Group] as g on g.ID = w.GroupID
left outer join [dbo].[GroupMember] as gm on gm.GroupID = g.ID
AND gm.ID = w.DepositedByMemberID
order by w.GroupID
var results = (from we in _repository.GetAll().ToList()
                join g in groups on we.GroupID equals g.ID into grpjoin
                from g in grpjoin.DefaultIfEmpty()
                join gm in groupMembers on we.DepositedByMemberID equals gm.ID into gmjoin
                from gm in gmjoin.DefaultIfEmpty()
                where gm.GroupID == g.ID
                select new {...}.ToList();
 var groups = _repositoryGroup.GetAll().OrderBy(o => o.ID)
                              .Select(s => new { s.ID, s.Name }).ToList();
 var groupMembers = _repositoryGroupMember.GetAll().OrderBy(o => o.ID)
                                          .Select(s => new { s.GroupID, s.ID, s.Name })
                                          .ToList();
public class GenericRepository<T>
{
    MyDbContext dbContext;
    public GenericRepository()
    {
        dbContext = new MyDbContext();
    }
    public IQueryable<T> GetAll()
    {
        // whatever
    }
}
_repository = new GenericRepository<WeeklyEntry>();
_repositoryGroup = new GenericRepository<Group>();
_repositoryGroupMember = new GenericRepository<GroupMember>();

var groups = _repositoryGroup.GetAll().ToList(); // other query operators are irrelevant and removed
var groupMembers = _repositoryGroupMember.GetAll().ToList();
var results = from we in _repository.GetAll() // <-- this is IQueryable<T>
              join g in groups                // <-- this is List<T> (IEnumerable<T>)
              on we.GroupID equals g.ID into grpjoin
              ...
using (var dbContext = new MyDbContext())
{
    var groups = dbContext.Set<Group>();
    var groupMembers = dbContext.Set<GroupMember>();

    var results = from we in dbContext.Set<WeeklyEntry>()
                  join g in groups
                  on we.GroupID equals g.ID into grpjoin
                  ...

}