代码优先多对多查询

时间:2013-01-29 10:22:51

标签: c# asp.net-mvc ef-code-first

我有一个代码表:

public class Code
{
    [Key]
    public int CodeID { get; set; }

    [Required]
    [StringLength(30)]
    public string Title { get; set; }

    [Required]
    [StringLength(150)]
    public string Description { get; set; }

    public DateTime DateAdded { get; set; }

    public DateTime LastUpdated { get; set; }

    [Required]
    [StringLength(30)]
    public string Project { get; set; }

    [Required]
    [StringLength(30)]
    public string CMS { get; set; }

    public int DotNetVersion { get; set; }

    [Required]
    [StringLength(150)]
    public string Dependencies { get; set; }

    [StringLength(30)]
    public string Author { get; set; }

    public string CodeFile { get; set; }

    [Required]
    [StringLength(100)]
    public string TFSLocation { get; set; }

    ////Creates a relationship in the DB with Tag
    //[ForeignKey("TagID")]
    public virtual ICollection<Tag> Tags { get; set; }

    ////Purely for API
    //[Required]
    public int TagID { get; set; }
}

标签表:

public class Tag
{
    [Key]
    public int TagID { get; set; }

    [Required]
    [StringLength(30)]
    public string TagName { get; set; }

    ////Creates a relationship in the DB with Code
    public virtual ICollection<Code> Code { get; set; }
}

一个视图模型:

public class CodeTagViewModel
{
    public List<Tag> Tags { get; set; }
    public List<Tag> SelectedTags { get; set; }        

    public int CodeID { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
    public DateTime DateAdded { get; set; }
    public DateTime LastUpdated { get; set; }
    public string Project { get; set; }
    public string CMS { get; set; }
    public int DotNetVersion { get; set; }
    public string Dependencies { get; set; }
    public string Author { get; set; }
    public string CodeFile { get; set; }
    public string TFSLocation { get; set; }

}

我正在尝试运行查询以获取链接到已搜索的标记名称的代码文件。目前我有这样的事情:

        List<CodeTagViewModel> models = new List<CodeTagViewModel>();
        List<Code> codes = db.Code.ToList<Code>();

        foreach (Code code in codes)
        {
            models.Add(MapCodeToModel(code));
        }

        var orderedModels = models.ToList();

        if (!String.IsNullOrEmpty(searchString))
        {
            orderedModels = models.Where(x => x.Title.ToUpper().Contains(searchString.ToUpper()) || x.Description.ToUpper().Contains(searchString.ToUpper()) || x.Project.ToUpper().Contains(searchString.ToUpper()) || x.CMS.ToUpper().Contains(searchString.ToUpper()) || x.Dependencies.ToUpper().Contains(searchString.ToUpper()) || x.Author.ToUpper().Contains(searchString.ToUpper())).ToList();

            if(orderedModels.Count == 0)
            {
                var Tags = db.Tags;
                 orderedModels = models.SelectMany(x => x.SelectedTags).Select(t => t).Where(t => t.TagName).Contains(searchString).ToList();
            }
        }

        return View(orderedModels);

根据代码表的其他列进行搜索工作正常,我只是将它们包含在内,这样您就可以更好地了解我想要做的事情;也许有一种比我的if语句更好的方法,看看搜索是否先匹配其他任何东西。它只是搜索似乎对我不起作用的标签。

我需要帮助的部分:

 orderedModels = models.SelectMany(x => x.SelectedTags).Select(t => t).Where(t => t.TagName).Contains(searchString).ToList();

2 个答案:

答案 0 :(得分:1)

假设您有一个标签枚举,您可以通过直接导航与代码文件的关系来找到代码文件 -

var tags = ... // enumeration of tags
var matches = tags.SelectMany(t => t.Code); 

编辑

查看您的代码,我不明白您在这里搜索的确切内容,但是假设您的搜索字符串应该与标记名称匹配,那么找到匹配的标记应该是直截了当的:

var tags = db.Tags.Where(t => t.TagName.ToUpper().Contains(searchString.ToUpper()));

修改
我不明白为什么你需要搜索模型。您可以直接搜索代码:

searchString = searchString.ToUpper();
var directMatches = db.Code.Where(c=> c.Title.ToUpper().Contains(searchString) ||
                        c.Description.ToUpper().Contains(searchString) ||    
                        ... (and so on)

这会在其他属性上提供匹配的代码文件,然后您可以将其与来自标记搜索的匹配结合起来以获取合并结果(directMatches.Union(matches))。

另外注意,谨慎使用ToList - 它实现当前查询以生成内存数据,因此代码声明如

List<Code> codes = db.Code.ToList<Code>();

这会将所有代码行从数据库带到内存。类似地,代码if(orderedModels == models.ToList())将不起作用,因为您正在比较两个不同内存列表的ToList调用的两个结果,并且它们的参考比较将失败。

答案 1 :(得分:0)

解决了它:

if(orderedModels.Count == 0)
            {
                var codesByTag = db.Code.Where(c => c.Tags.Any(t => t.TagName.ToUpper().Contains(searchString))).ToList<Code>();
                foreach (var searchResult in codesByTag)
                {
                    orderedModels.Add(MapCodeToModel(searchResult));
                }
            }

MapCodeToModel是我自己的自解释方法,如果有帮助我可以发帖请求。