我可以使用LINQ在SQL Server上的IQueryable上进行连接吗?

时间:2013-07-05 20:07:13

标签: sql-server linq entity-framework entity-framework-4

我有两张桌子。问题和用户档案

    public QuestionMap()
    {
        this.HasKey(t => t.QuestionId);

        this.Property(t => t.Title)
            .IsRequired()
            .HasMaxLength(100);

        this.Property(t => t.CreatedBy)
            .IsRequired();
    }

    public UserProfileMap()
    {
        this.HasKey(t => t.UserId);

        this.Property(t => t.UserName)
            .IsRequired()
            .HasMaxLength(56);
    }

我的存储库调用目前看起来像这样:

    public virtual IQueryable<T> GetAll()
    {
        return DbSet;
    }

有没有办法可以更改存储库调用,以便它将转到数据库,加入Question和UserProfile表,然后从UserProfile表中恢复具有UserName的列表?我意识到我可能必须为返回类型创建另一个类(包括UserName),我可以这样做。

3 个答案:

答案 0 :(得分:2)

您无法将属性映射配置为已连接实体的某些字段。但您可以在Question和UserProfile entites中创建导航属性,这将提供加入的enitites:

public class Question
{
    public int QuestionId { get; set; }
    public string Title { get; set; }
    public virtual UserProfile CreatedBy { get; set; }
}

public class UserProfile
{
    public int UserId { get; set; }
    public string UserName { get; set; }
    public virtual ICollection<Question> Questions { get; set; }
}

并将映射配置添加到用户映射:

HasMany(u => u.Questions)
    .WithRequired(q => q.CreatedBy)
    .Map(m => m.MapKey("UserId"))
    .WillCascadeOnDelete(true);

现在,您可以在查询问题时急切地加载用户:

var questions = context.Questions.Include(q => q.CreatedBy);
foreach(var question in questions)
    Console.WriteLine(question.CreatedBy.UserName);

答案 1 :(得分:0)

您应该在控制器中进行连接而不是存储库。存储库应该只处理数据库中的一个实体。

或者您可以在数据库中创建一个View,并将其作为实体添加到您的实体框架模型中。

答案 2 :(得分:0)

实际上,you CAN join tables using LINQ without navigation properties.让我演示:

public class Question
{
    public int QuestionID { get; set; }
    public string Title { get; set; }
    public string TextBody { get; set; }
    public int CreatedBy { get; set; }
}

public class UserProfile
{
    [Key]
    public int UserID { get; set; }
    public string UserName { get; set; }
    public string Password { get; set; }
}

这就是(非常简单)的模型。现在,我对OP的帖子中显示的IQueryable<T> GetAll()方法一点都不熟悉,但是我假设这个方法可以用来返回一个IQueryable<Question>,当执行时,它将获得所有来自数据库的问题。在我的示例中,我将改为使用MyDbContext,但如果您愿意,可以使用其他方法替换它...

所以LINQ连接将按如下方式完成:

public void SomeMethod()
{
    var results = MyDbContext.Questions.Join(MyDbContext.UserProfiles,
        q => q.CreatedBy,
        u => u.UserID,
        (q,u) => new {
            q.QuestionID,
            q.Title,
            q.TextBody,
            u.UserName
        });
    foreach (var result in results)
    {
        Console.WriteLine("User {0} asked a question titled {1}:",
            result.UserName, result.Title);
        Console.WriteLine("\t{0}", result.TextBody)
    }
}

现在,我确实认为导航属性对于这种明显和常见的关系来说更好。但是,有时您可能不希望为很少引用的关系添加导航属性。在这些情况下,使用Join方法可能更好。