Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/323.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# 无法在LINQ to Entities查询中构造实体_C#_Entity Framework - Fatal编程技术网

C# 无法在LINQ to Entities查询中构造实体

C# 无法在LINQ to Entities查询中构造实体,c#,entity-framework,C#,Entity Framework,实体框架生成了一个名为Product的实体类型。 我写了这个查询 public IQueryable<Product> GetProducts(int categoryID) { return from p in db.Products where p.CategoryID== categoryID select new Product { Name = p.Name}; } 但是当我使用选择p而不是选择新产品{Name=p.Na

实体框架生成了一个名为
Product
的实体类型。 我写了这个查询

public IQueryable<Product> GetProducts(int categoryID)
{
    return from p in db.Products
           where p.CategoryID== categoryID
           select new Product { Name = p.Name};
}
但是当我使用
选择p
而不是
选择新产品{Name=p.Name}它工作正常

如何执行自定义选择节?

您不能(也不应该能够)投影到映射的实体上。但是,您可以投影到匿名类型或:

您的方法将返回DTO的列表

public List<ProductDTO> GetProducts(int categoryID)
{
    return (from p in db.Products
            where p.CategoryID == categoryID
            select new ProductDTO { Name = p.Name }).ToList();
}
public List GetProducts(int categoryID)
{
返回(来自数据库产品中的p)
其中p.CategoryID==CategoryID
选择newproductdto{Name=p.Name}).ToList();
}
另一种简单的方法:)

public IQueryable GetProducts(int categoryID)
{
var productList=db.Products
.其中(p=>p.CategoryID==CategoryID)
.选择(项目=>
新产品
{
Name=项目名称
})
托利斯先生()
.AsQueryable();//实际上,在“ToList()”之后它没有用处:D
返回产品列表;
}

我发现还有另一种方法可行,您必须构建一个从产品类派生的类并使用它。例如:

public class PseudoProduct : Product { }

public IQueryable<Product> GetProducts(int categoryID)
{
    return from p in db.Products
           where p.CategoryID== categoryID
           select new PseudoProduct() { Name = p.Name};
}
公共类伪产品:产品{}
公共IQueryable GetProducts(内部类别ID)
{
从p返回,单位为db.Products
其中p.CategoryID==CategoryID
选择new PseudoProduct(){Name=p.Name};
}

不确定这是否是“允许的”,但它是有效的。

这里有一种不声明传统类的方法:

public List<Product> GetProducts(int categoryID)
{
    var query = from p in db.Products
            where p.CategoryID == categoryID
            select new { Name = p.Name };
    var products = query.ToList().Select(r => new Product
    {
        Name = r.Name;
    }).ToList();

    return products;
}
public List GetProducts(int categoryID)
{
var query=来自数据库产品中的p
其中p.CategoryID==CategoryID
选择新的{Name=p.Name};
var products=query.ToList()。选择(r=>newproduct
{
名称=r.名称;
}).ToList();
退货产品;
}
但是,仅当您希望将多个实体合并到一个实体中时才使用此选项。上述功能(简单的产品到产品映射)是这样完成的:

public List<Product> GetProducts(int categoryID)
{
    var query = from p in db.Products
            where p.CategoryID == categoryID
            select p;
    var products = query.ToList();

    return products;
}
int categoryID = 1;
var prods = repository.GetProducts(categoryID);
public List GetProducts(int categoryID)
{
var query=来自数据库产品中的p
其中p.CategoryID==CategoryID
选择p;
var products=query.ToList();
退货产品;
}

您可以投影到匿名类型,然后从它投影到模型类型

public IEnumerable<Product> GetProducts(int categoryID)
{
    return (from p in Context.Set<Product>()
            where p.CategoryID == categoryID
            select new { Name = p.Name }).ToList()
           .Select(x => new Product { Name = x.Name });
}
public IEnumerable GetProducts(int categoryID)
{
返回(来自Context.Set()中的p)
其中p.CategoryID==CategoryID
选择新建{Name=p.Name}).ToList()
.Select(x=>新产品{Name=x.Name});
}
编辑:由于这个问题受到了广泛关注,我将更具体一点

您不能直接投影到模型类型中(EF限制),因此无法解决此问题。唯一的方法是投射到匿名类型(第一次迭代),然后投射到模型类型(第二次迭代)

还请注意,当您以这种方式部分加载实体时,它们无法更新,因此它们应该保持分离状态

我从来没有完全理解为什么这是不可能的,并且这个线程上的答案没有给出强烈的反对理由(主要是关于部分加载的数据)。在部分加载状态下,实体无法更新是正确的,但这样,该实体将被分离,因此不可能意外尝试保存它们

考虑我在上面使用的方法:结果我们仍然有一个部分加载的模型实体。此实体已分离

考虑以下(希望存在)可能的代码:

return (from p in Context.Set<Product>()
        where p.CategoryID == categoryID
        select new Product { Name = p.Name }).AsNoTracking().ToList();
return(来自Context.Set()中的p)
其中p.CategoryID==CategoryID
选择新产品{Name=p.Name}).AsNoTracking().ToList();

这还可能导致分离实体的列表,因此我们不需要进行两次迭代。编译器会很聪明地看到使用了AsNoTracking(),这将导致分离实体,因此它可以允许我们这样做。但是,如果省略了AsNoTracking(),它可能会抛出与现在相同的异常,以警告我们需要对我们想要的结果足够具体。

针对另一个标记为重复()的问题,我根据Soren的答案想出了一个快速而简单的解决方案:

data.Tasks.AddRange(
    data.Task.AsEnumerable().Select(t => new Task{
        creator_id   = t.ID,
        start_date   = t.Incident.DateOpened,
        end_date     = t.Incident.DateCLosed,
        product_code = t.Incident.ProductCode
        // so on...
    })
);
data.SaveChanges();
注: 此解决方案仅在任务类(此处称为“事件”)上具有导航属性(外键)时有效。
如果您没有,您可以使用其他发布的解决方案中的一个与“AsQueryable()”配合使用。

如果您使用的是实体框架,那么请尝试从使用复杂模型作为实体的DbContext中删除属性 我在将多个模型映射到名为Entity的viewmodel时遇到了相同的问题

public DbSet<Entity> Entities { get; set; }
公共数据库集实体{get;set;}

从DbContext中删除条目修复了我的错误。

您可以使用它,它应该可以工作-->在使用select创建新列表之前,必须使用
toList

db.Products
    .where(x=>x.CategoryID == categoryID).ToList()
    .select(x=>new Product { Name = p.Name}).ToList(); 

如果您正在执行
Linq to Entity
,则在
select
closure of query
中,不能将
ClassType
new
一起使用

看看我的项目的这个片段

//...
var dbQuery = context.Set<Letter>()
                .Include(letter => letter.LetterStatus)
                .Select(l => new {Title =l.Title,ID = l.ID, LastModificationDate = l.LastModificationDate, DateCreated = l.DateCreated,LetterStatus = new {ID = l.LetterStatusID.Value,NameInArabic = l.LetterStatus.NameInArabic,NameInEnglish = l.LetterStatus.NameInEnglish} })
                               ^^ without type__________________________________________________________________________________________________________^^ without type

在我对查询执行了
ToList
之后,它就变成了
内存集合
,因此我们可以在select中使用
新类类型
您可以通过使用数据传输对象(DTO)来解决这个问题

这些有点像viewmodels,您可以在其中输入所需的属性,并可以在控制器中手动映射它们,或者使用第三方解决方案(如AutoMapper)来映射它们

使用DTO,您可以:

  • 使数据可序列化(Json)
  • 去掉循环引用
  • 保留不需要的属性以减少网络流量(viewmodelwise)
  • 使用对象展平
今年我在学校里学的
db.Products
    .where(x=>x.CategoryID == categoryID).ToList()
    .select(x=>new Product { Name = p.Name}).ToList(); 
//...
var dbQuery = context.Set<Letter>()
                .Include(letter => letter.LetterStatus)
                .Select(l => new {Title =l.Title,ID = l.ID, LastModificationDate = l.LastModificationDate, DateCreated = l.DateCreated,LetterStatus = new {ID = l.LetterStatusID.Value,NameInArabic = l.LetterStatus.NameInArabic,NameInEnglish = l.LetterStatus.NameInEnglish} })
                               ^^ without type__________________________________________________________________________________________________________^^ without type
//opecations in tempList , LINQ to Entities; so we can not use class types in select only anonymous types are allowed
var tempList = dbQuery.Skip(10).Take(10).ToList();// this is list of <anonymous type> so we have to convert it so list of <letter>

//opecations in list , LINQ to Object; so we can use class types in select
list = tempList.Select(l => new Letter{ Title = l.Title, ID = l.ID, LastModificationDate = l.LastModificationDate, DateCreated = l.DateCreated, LetterStatus = new LetterStatus{ ID = l.LetterStatus.ID, NameInArabic = l.LetterStatus.NameInArabic, NameInEnglish = l.LetterStatus.NameInEnglish } }).ToList();
                                ^^^^^^ with type 
public IQueryable<Product> GetProducts(int categoryID)
{
    return from p in db.Products.AsEnumerable()
           where p.CategoryID== categoryID
           select new Product { Name = p.Name};
}
public IQueryable<Product> GetProducts(int categoryID)
{
    return from p in db.Products.AsEnumerable()
           where p.CategoryID== categoryID
           select new Product { Name = p.Name};
}
IEnumerable<object> list = dataContext.Table.Select(e => new { MyRequiredField = e.MyRequiredField}).AsEnumerable();
public class ProductViewModel
{
    [Key]
    public string ID { get; set; }
    public string Name { get; set; }
}
int categoryID = 1;
var prods = repository.GetProducts(categoryID);
public IEnumerable<ProductViewModel> GetProducts(int categoryID)
{
   List<ProductViewModel> lstPVM = new List<ProductViewModel>();

   var anonymousObjResult = from p in db.Products
                            where p.CategoryID == categoryID 
                            select new
                            {
                                CatID = p.CategoryID,
                                Name = p.Name
                            };

        // NOTE: If you have any dates that are nullable and null, you'll need to
        // take care of that:  ClosedDate = (DateTime?)p.ClosedDate ?? DateTime.Now

        // If you want a particular date, you have to define a DateTime variable,
        // assign your value to it, then replace DateTime.Now with that variable. You
        // cannot call a DateTime.Parse there, unfortunately. 
        // Using 
        //    new Date("1","1","1800"); 
        // works, though. (I add a particular date so I can edit it out later.)

        // I do this foreach below so I can return a List<ProductViewModel>. 
        // You could do: return anonymousObjResult.ToList(); here
        // but it's not as clean and is an anonymous type instead of defined
        // by a ViewModel where you can control the individual field types

        foreach (var a in anonymousObjResult)
        {                
            ProductViewModel pvm = new ProductViewModel();
            pvm.ID = a.CatID;  
            pvm.Name = a.Name;
            lstPVM.Add(rvm);
        }

        // Obviously you will just have ONE item there, but I built it 
        // like this so you could bring back the whole table, if you wanted
        // to remove your Where clause, above.

        return lstPVM;
    }
 List<ProductViewModel> lstProd = new List<ProductViewModel>();

 if (prods != null) 
 {
    // For setting the dates back to nulls, I'm looking for this value:
    // DateTime stdDate = DateTime.Parse("01/01/1800");

    foreach (var a in prods)
    {
        ProductViewModel o_prod = new ReportViewModel();
        o_prod.ID = a.ID;
        o_prod.Name = a.Name;
       // o_prod.ClosedDate = a.ClosedDate == stdDate ? null : a.ClosedDate;
        lstProd.Add(o_prod);
    }
}
return View(lstProd);  // use this in your View as:   @model IEnumerable<ProductViewModel>