0

I am having trouble to return an IEnumerable and IList, I cant do it! I am using EF 4 with POCOs

Here's the whole method:

//public IList<Genre> GetGenresByGame(int gameId)
public IEnumerable<Genre> GetGenresByGame(int gameId)
    {
        using(var ctx = new XContext())
        {
            var results =
                    from t0 in ctx.GameGenres
                    join t1 in ctx.GenreCultureDetails on t0.GenreId equals t1.GenreId
                    where t0.GameId == gameId && t1.CultureId == _cultureId
                    select new Genre
                    {
                        GenreId = t0.GenreId,
                        GenreName = t1.GenreName

                    };

            return results.ToList(); 
        }
    }

I have tried different ways that I have found on the net.. but can't make it work!

Question 2: I saw a screencast with Julie something, saying that "You should always return an ICollection" when using EF4.

Any thoughts about that ?

BR

EDIT: When I load the page in Debug-mode i get these errors: The ObjectContext instance has been disposed and can no longer be used for operations that require a connection. OR The entity or complex type 'XModel.Genre' cannot be constructed in a LINQ to Entities query.

Snowbear
  • 16,924
  • 3
  • 43
  • 67
n3tx
  • 429
  • 2
  • 10
  • 23
  • Just a random question, but does Genre exist in your db? And if so, why aren't you just selecting that? – Nix Mar 17 '11 at 20:18
  • Yes, Genre do exist in the database. Select, how do you mean ? – n3tx Mar 17 '11 at 20:20
  • See below, for details I can update if you provide more information on your table structure. – Nix Mar 17 '11 at 20:54
  • @Nix what info you need ? I got three tables, Genres (GenreId), GameGenres (MAP GenreId, GameId) and GenreCultureDetail (CultureId, GenreId, GenreName) – n3tx Mar 17 '11 at 21:19

2 Answers2

2

Genre must not be a L2EF type. Try this:

public IEnumerable<Genre> GetGenresByGame(int gameId)
{
    using(var ctx = new XContext())
    {
        var resultList =
                from t0 in ctx.GameGenres
                join t1 in ctx.GenreCultureDetails on t0.GenreId equals t1.GenreId
                where t0.GameId == gameId && t1.CultureId == _cultureId
                select new { t0.GenreId, t1.GenreName };
        var genres = resultList.AsEnumerable().Select(o => new Genre
                     {
                         GenreId = o.GenreId,
                         GenreName = o.GenreName
                     });
        return genres.ToList();
    }
}
n3tx
  • 429
  • 2
  • 10
  • 23
BlueRaja - Danny Pflughoeft
  • 84,206
  • 33
  • 197
  • 283
  • I believe it would be better to use `AsEnumerable` firstly (where you have `ToList`) and then `ToList` at the end. – Snowbear Mar 17 '11 at 20:33
  • @Snowbear: `AsEnumerable()` won't execute the query (in fact, it won't do anything), and thus will cause the same problem OP is having. See http://stackoverflow.com/questions/3389855/am-i-misunderstanding-linq-to-sql-asenumerable/3389908#3389908 – BlueRaja - Danny Pflughoeft Mar 17 '11 at 20:36
  • @BlueRaja, correct, you don't need immediate execution at that point, you need it somewhere within that method. All you need is to treat next `Select` as `IEnumerable.Select` instead of `IQueryable.Select` and `AsEnumerable` will do it. – Snowbear Mar 17 '11 at 20:38
  • @BlueRaja, thanks, but you would still need `ToList` otherwise it won't be executed at all. I just wanted to say that `ToList` can be moved couple of lines below than you had originally. It will make your method return regular `List` instead of `List` with projection over it as you had firstly. Anyway your answers seems to be correct. – Snowbear Mar 17 '11 at 20:43
  • ANSWER 1 worked when I added the ToList(), return genres.ToList(); – n3tx Mar 17 '11 at 21:01
  • How can you do it with .Include instead of join ? – n3tx Mar 17 '11 at 21:22
  • @n3tx: Assuming you have the entity-relationship set up, `from t in ctx.GameGenres.Include("GenreCultureDetails") where t.GameId == gameId && t.GenreCultureDetails.CultureId == _cultureId select new { t.GenreId, t.GenreCultureDetails.GenreName };` – BlueRaja - Danny Pflughoeft Mar 17 '11 at 21:24
0

First an foremost if Genre is in the database you should select it? If you have FKs from Genre->GenreCultureDetails let me know and I can update the below, but from the looks of it you could do it like this:

using(var ctx = new XContext())
{
    var results =
            from g in ctx.Genre
            join gcd in ctx.GenreCultureDetails on g.GenreId equals gcd.GenreId
            where g.GameId == gameId && gcd.CultureId == _cultureId
            select g;


    return result.ToList();
}

Alternatively continue down your path select them into an annoynmous type, and then copy them. You can use select instead of convertall if you please.

IList<Genre> returnMe = Null;
using(var ctx = new XContext())
{
    var results =
            from t0 in ctx.GameGenres
            join t1 in ctx.GenreCultureDetails on t0.GenreId equals t1.GenreId
            where t0.GameId == gameId && t1.CultureId == _cultureId
            select new
            {
                GenreId = t0.GenreId,
                GenreName = t1.GenreName

            };

    returnMe  = results.ToList().ConvertAll(x=>new Genre(){
                           GenreId = x.GenreId,
                           GenreName = x.GenreName
                           }
          );
}
return returnMe;
Nix
  • 57,072
  • 29
  • 149
  • 198
  • what's the point in your two changes? `AsEnumerable` won't affect it anyhow, `Genre` without `()` is just a syntax sugar. – Snowbear Mar 17 '11 at 20:08
  • The brackets don't change anything. `new Genre() { GenreID = xyz };` and `new Genre { GenreID = xyz };` is the same. – magnattic Mar 17 '11 at 20:11
  • that's funny but NOW you should use `AsEnumerable` instead of `ToList()` – Snowbear Mar 17 '11 at 20:14
  • `AsEnumerable` won't create useless `List`. – Snowbear Mar 17 '11 at 20:18
  • ANSWER 0 gives me: Cannot implicitly convert type 'System.Collections.Generic.List' to 'System.Linq.IQueryable' – n3tx Mar 17 '11 at 20:53
  • It's because of the results = results it was changing the type see above just return it or create another variable. – Nix Mar 17 '11 at 20:56
  • `AsEnumerable` won't create needless `List` in memory which will be important if you have a lot of rows to be returned from DB. Even though in your case `List` will be disposed almost instantly, but you will still create two `Lists` and allocate memory for both of them. – Snowbear Mar 17 '11 at 20:56
  • Are you mistaking AsQuerable and AsEnumerable? Because AsEnumerable will load to memory... as enumerable will convert it to LinqToObjects... which is in memory ... – Nix Mar 17 '11 at 20:58
  • I am a little confused about IList and IEnumerable, what is best practies for using any of them ? Cons och pros ? – n3tx Mar 17 '11 at 21:12
  • If you are going to be modifying it use ILIst, if you are just going to be iterating over it use IEnumerable. – Nix Mar 18 '11 at 01:25