实体框架:如何从单一导航属性中选择特定字段?

时间:2013-12-23 16:51:43

标签: sql .net entity-framework

我有以下实体:

public class Movie
{
    public int    MovieID      { get; set; }
    public int?   DirectorID   { get; set; }
    public string Title        { get; set; }

    public Person               Director   { get; set; }
    public ICollection<Person>  Actors     { get; set; }    
}

//Director Config:
//HasOptional(m => m.Director).WithMany().HasForeignKey(m => m.DirectorID);


public class Person
{
    public int    PersonID  { get; set; }
    public string FirstName { get; set; }
    public string LastName  { get; set; }
    //Other fields....
}

Person实体有其他字段,而不是我所展示的3,但那些是我感兴趣的3。为了创建一个网页来编辑电影实体我希望返回这样的数据:

var q = _ctx.Movies.Where(m => m.MovieID == movieID);
q = q.Include(m => m.Director);
return q.Select(m => new
{
    MovieID        = m.MovieID,
    Name           = m.Title,
    Director       = m.Director == null ? null : new { id= m.Director.PersonID, text=m.Director.LastName} 
}).Single();

目标是返回一个Director属性的对象,如果没有设置Director,则该属性为null;如果已设置Director,则返回具有2个属性的对象id和text(name)。将此场景的整个人员实体返回给客户端会有点过分。不幸的是,上述查询无效。

有没有选择做这样的事情?替代?

非常感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

如果没有导演,则实体框架无法将匿名类型设置为null。

一个很好的解决方法可能是在类型中添加一个标志来指示电影是否有导演,如果不是这样的话,只需将其他属性设置为某些虚拟值。

然后,您可以在访问任何实际值之前检查该标志。

using (var ctx = new Context())
{
    var movie =
        (from m in ctx.Movies.Include(p => p.Director)
        where m.MovieID == 3
        let hasDirector = m.Director != null
        select new
        {
            MovieID = m.MovieID,
            Name = m.Title,
            Director = new
            {
                Id = hasDirector ? m.Director.PersonID : -1,
                Text = hasDirector ? m.Director.LastName : null,
                Exists = hasDirector
            }
        }).SingleOrDefault();

    if (movie != null)
    {
        Console.WriteLine("Movie name: " + movie.Name);

        if (movie.Director.Exists)
        {
            Console.WriteLine("Director id: " + movie.Director.Id.ToString());
            Console.WriteLine("Director text: " + movie.Director.Text);
        }
        else
        {
            Console.WriteLine("Movie has no director..");
        }
    }
}

答案 1 :(得分:0)

您可以创建ignored property DirectorExists并按照指定的方式填写。

使用CreateSourceQuery创建查询并检查Director是否存在并设置DirectorExists属性。

如果您的实体派生自EntityObject

 Movie m;
 ....

 m.DirectorExists = m.DirectorReference.CreateSourceQuery().Any();

如果你有POCO,你可以加载你的电影,包括你的方式,然后在将对象发送到客户端之前将Director设置为null。

更新:如果你上面有代理启用的代码可能也可以,但我没有这样的项目来尝试。

您还可以考虑实际更改数据模型,以便在Movie表中包含DirectoExists字段,并在为Movie设置Directors时更新它。这样,在加载Movie对象时,您不需要Include