使用lambda表达式在RenderAction视图中访问多个到一个Entity Framework模型属性

时间:2015-09-23 15:12:48

标签: c# entity-framework lambda renderaction

我尝试在FilePath操作中访问模型(Render)的属性,但没有成功。

我有这些模特:

public class Offer
{
 public int OfferID { get; set; }
 public string Reference { get; set; }
 public string Title { get; set; }

 public virtual ICollection<FilePath> FilePaths { get; set; }
}

public class FilePath
{
 public int FilePathId { get; set; }
 public string FileName { get; set; }
 public virtual Offer Offer { get; set; }
}

在控制器提供中:

public PartialViewResult Category()
{
 var offers = db.Offers
 .Include(i => i.FilePaths)
 // i tried with .Include(“FilePaths”) with no sucess
 .ToList();
  return PartialView("_OfferBoxList", offers);
}

显示:

@{Html.RenderAction("Category", "Offer");}

问题出在部分行动视图中:

@foreach (var item in Model)
{
 @item.Title // This work
 @item.FilePath.FileName // This NOT work
}

输出错误:

  

&#39; System.Data.Entity.DynamicProxies.Offer_278BF6A1F89FB9514329AC922E992AEBD19368D66A4460B6BEBA1BB2256CAFC3&#39;不包含&#39; FilePath&#39;

的定义

感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

每个Offer都有一个FilePath个实例列表(ICollection<FilePath> FilePaths),因此您无法访问Offer.FilePath.FileName属性,例如,您必须获取第一个(取决于你需要的),使用类似的东西:

@foreach (var item in Model)
{
     @item.Title // This work
     @item.FilePaths.First().FileName // Take the first FilePath object from the collection
}

答案 1 :(得分:0)

你真的不应该将你的实体加载到视图中..

我通常会出于多种目的创建数据传输对象(DTO)。它不仅帮助我塑造查询表达式(IQueryable<T>),而且还使用了我的Concert类型(而不是生成的动态代理类类型 - 就像你在运行时异常中看到的类型一样) )在控件属性中,如dataItemdataSource,它们通常用于运行时可绑定的动态/反射控件(网格,列表视图)..

<强> 注意  可以通过声明并将您自己的DbContextConfiguration实例传递给EntityFramework来禁用生成的动态代理类型;但是,这样做会影响EntityFramework支持功能。

public class OfferDTO
{
    public int OfferID { get; set; }
    public string Reference { get; set; }
    public string Title { get; set; }
    public IEnumerable<string> FileNames { get; set; }
}

你的控制器功能如下:

public PartialViewResult Category()
{
    var offers = db.Offers.Select<Offer, OfferDTO>( (entity) => new OfferDTO() {
        OfferID = entity.OfferID,
        Reference = entity.Reference,
        Title = entity.Title,
        FileNames = entity.FilePaths.Select<FilePath, string>( filePath => filePath.FileName).AsEnumerable()
    });

    return PartialView("_OfferBoxList", offers.ToList());
}

然后,

@{Html.RenderAction("Category", "OfferDTO");}

@foreach (var item in Model) // Model is IEnumerable<OfferDTO>
{
    @item.Title 
    @item.FileNames.First()
}

另外,

您可以创建IQueryable<IQueryable<TEntityDTO>>以符合您的目的,并在其上执行SelectMany以平展结果。

public class OfferTitleFilenameDTO
{
    public string Title {get;set;}
    public string Filename {get;set;}
}

public PartialViewResult Category()
{
    var offers = db.Offers.Select<Offer, IQueryable<OfferTitleFilenameDTO>>( (entity) => entity.FilePaths.Select<FilePath, OfferTitleFilenameDTO>(filePath => new OfferTitleFilenameDTO() {
            Filename = filePath.FileName,
            Title = entity.Title
        })
    });

    return PartialView("_OfferBoxList", offers.SelectMany(dtos => dtos));
}

然后,

@{Html.RenderAction("Category", "OfferTitleFilenameDTO");}

@foreach (var item in Model) // Model is IEnumerable<OfferTitleFilenameDTO>
{
    @item.Title 
    @item.Filename 
}