获取与实体框架6的多对多关系中的随机对象

时间:2014-11-20 21:08:19

标签: asp.net-mvc entity-framework asp.net-mvc-5 entity-framework-6

我有以下2个型号:

public class CrawledImage
{
    public CrawledImage()
    {
        CrawlDate = DateTime.UtcNow;
        Status = ImageStatus.Unchecked;
    }

    public int ID { get; set; }
    public DateTime CrawlDate { get; set; }
    public string FileUrl { get; set; }
    public long Bytes { get; set; }
    public ImageStatus Status { get; set; }
    public string FileName { get; set; }
    public string Type { get; set; }
    public virtual ICollection<ImageTag> ImageTags { get; set; }
}

public class ImageTag
{
    public ImageTag()
    {
    }

    public int ID { get; set; }
    public string Name { get; set; }
    public virtual ICollection<CrawledImage> CrawledImages { get; set; }
}

现在我想要的是获得一个随机的CrawledImage,它不是当前的图像,它包含我在List中提供的所有标记(或者Collection的HashSet并不重要)。请注意,这是多对多的关系。我尝试使用下面的代码,但我失败了所以我评论了有关标签的部分。我更喜欢使用Entity Framework执行此操作。

public static CrawledImage GetRandomImage(int currentid, List<ImageTag> listtags)
{
    try
    {
        while (true)
        {
            var randomId = new Random().Next(0, DbContext.CrawledImages.Count());

            if (!randomId.Equals(currentid))
            {
                var image =
                    DbContext.CrawledImages.Single(i => i.ID.Equals(randomId));
                    //DbContext.CrawledImages.Where(i => i.ImageTags.Any(tag => listtags.Contains(tag))).First();
                if (ProcessImage(image))
                    return image;
            }
        }
    }
    catch (Exception ex)
    {
        // Failed so return image with id -1
        return new CrawledImage {ID = -1};
    }
}

谢谢!

修改 我的问题被标记为重复。它只涉及一个关于检索随机记录的问题。我得到了这个工作。它更多的是关于多对多的关系。下面有一个答案,但这给了我错误:

类型&#39; System.NotSupportedException&#39;的例外情况发生在EntityFramework.SqlServer.dll但未在用户代码中处理附加信息:无法创建类型为&#39; ChickSpider.Logic.Models.ImageTag&#39;的常量值。在此上下文中仅支持原始类型或枚举类型。

编辑2:

在Shoe的答案的帮助下我明白了。这是代码

public static CrawledImage GetRandomImage(int currentid = 0, HashSet<string> tags = null)
{
    if (tags == null)
        return DbContext.CrawledImages.Where(c => c.ID != currentid).OrderBy(c => Guid.NewGuid()).First();

    // ImageTags should match any given tags
    return DbContext.CrawledImages.Where(c => c.ID != currentid && c.ImageTags.Any(ci => tags.Any(lt => lt == ci.Name))).OrderBy(c => Guid.NewGuid()).First();

    // ImageTags should match all given tags
    //return DbContext.CrawledImages.Where(c => c.ID != currentid && c.ImageTags.All(ci => tags.Any(lt => lt == ci.Name))).OrderBy(c => Guid.NewGuid()).First();
}

1 个答案:

答案 0 :(得分:0)

您可以用更少的代码完成此任务......

//All crawledImages not equal to current image and contain listtags
var crawledImages = DbContext.CrawledImages.Where(ci => ci.ID != currentid && 
                    ci.ImageTags.All(ci => listtags.Any(lt => lt.ID == ci.ID));

var random = new Random();
var randImage = crawledImages.OrderBy(ci => random.Next()).FirstOrDefault();

另一个注意事项(可能是个人偏好?)我不会从方法中返回虚拟数据。

catch (Exception ex)
{
    //Log exception
    //..
    return null;
}