0

I got the following 2 models:

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; }
}

Now what i want is to get a random CrawledImage, which is not the current image and which has all the tags i supply in a List (or HashSet of Collection that doesn't matter). Note that this is a many to many relation. I tried with the code below but i failed so i commented the part about the tags. I prefer to do this with 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};
    }
}

Thanks!

Edit: My question was marked as duplicated. It linked to a question only about retrieving a random record. I got this working. It is more about the many to many relation. Below there is an answer on that but that gives me the error:

An exception of type 'System.NotSupportedException' occurred in EntityFramework.SqlServer.dll but was not handled in user code Additional information: Unable to create a constant value of type 'ChickSpider.Logic.Models.ImageTag'. Only primitive types or enumeration types are supported in this context.

Edit 2:

With the help from Shoe's answer i figured it out. Here is the code

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();
}
Fortitude
  • 55
  • 6

1 Answers1

0

You might be able to accomplish this in less code...

//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();

On Another note (maybe personal preference?) I wouldn't return dummy data from the method.

catch (Exception ex)
{
    //Log exception
    //..
    return null;
}
jamesSampica
  • 12,230
  • 3
  • 63
  • 85
  • I agree on the dummy data part. But i get the following exception on the last line: An exception of type 'System.NotSupportedException' occurred in EntityFramework.SqlServer.dll but was not handled in user code Additional information: Unable to create a constant value of type 'ChickSpider.Logic.Models.ImageTag'. Only primitive types or enumeration types are supported in this context. When i tried to debug in crawledImages i see the same exception. I also tried to remove the virtual on both collections but that didn't help either. – Fortitude Nov 20 '14 at 22:48