0

Question I'm trying something new here with a program I made earlier. In the first program I was able to drag and drop table adapters and use the generic "var" to store query results. Now I'm trying to create a new program that has some separation of code. For example in the first program I had all of the code written in the form.cs file, this time I'd like to create a class to run the queries and return them to the calling class, however, how do you store a query result that contains many types? You cant return a var variable, it must be more specific. I get an error on the select line that reads: "Cannot implicitly convert type'System.Collections.Generic.IEnumerable' to 'System.Collections.Generic.IEnumerable;. An explicit conversion exists(are you missing a cast?)

Can some one help me? What is the cast? The first method (public IEnumerable getList()) works as expected its the second method, (public IEnumerable getRecipeInfo(string recipeName)) where I get the error. Here's my code so far.

namespace recipeDataBase
{
    class Query
    {
        recipiesNewDataSet recipeDataSet = new recipiesNewDataSet();
        recipiesNewDataSetTableAdapters.RecipeTableAdapter recipeTableAdapter = new recipiesNewDataSetTableAdapters.RecipeTableAdapter();
        recipiesNewDataSetTableAdapters.RecipeIngredientTableAdapter ingredientTableAdapter = new recipiesNewDataSetTableAdapters.RecipeIngredientTableAdapter();
        recipiesNewDataSetTableAdapters.RatingTableAdapter ratingTableAdapter = new recipiesNewDataSetTableAdapters.RatingTableAdapter();

        public  Query()
        {

        }

        public IEnumerable<string> getList()
        {
            recipeTableAdapter.Fill(recipeDataSet.Recipe);

            IEnumerable<string> recipeList = (from a in recipeDataSet.Recipe
                                              select a.RecipeName);
            return recipeList;
        }

        public IEnumerable<string> getRecipeInfo(string recipeName)
        {
            recipeTableAdapter.Fill(recipeDataSet.Recipe);
            ratingTableAdapter.Fill(recipeDataSet.Rating);
            ingredientTableAdapter.Fill(recipeDataSet.RecipeIngredient);
            IEnumerable<string> recipeInfo = (from a in recipeDataSet.Recipe
                                              from b in recipeDataSet.Rating
                                              from c in recipeDataSet.RecipeIngredient
                                              where a.RecipeName == recipeName &&
                                              a.RecipeNum == c.RecipeNum &&
                                              a.RatingNum == b.RatingNum
                                              select new { a.RecipeName, a.Nationality, a.Event, a.Source, b.FamilyRating, c.Ingredient });
            return recipeInfo;
        }

    }
}

Thanks in advance for any help!!

L.B
  • 114,136
  • 19
  • 178
  • 224
Craig Smith
  • 583
  • 3
  • 9
  • 26

2 Answers2

1

You're getting an exception because you select an anonymous type in your query but the type of the query variable is IEnumerable<string>. Instead you must either select a string, use the var keyword or a custom class instead.

If you want to return something useful, i would create a custom class with all of these properties you have selected in the anonymous type, for example:

public class Recipe
{
    public String RecipeName{ get; set;}
    public String Nationality{ get; set;}
    public String Event{ get; set;}
    // ...
}

Then you can return an IEnumerable<Recipe> instead from the method and select instances in the query:

...
select new Recipe(){ RecipeName=a.RecipeName, Nationality=a.Nationality, Event=a.Event,... });

Side-note: I would suggest to use Join instead of Where in the query:

Why is LINQ JOIN so much faster than linking with WHERE?

Community
  • 1
  • 1
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • Ok so I created a new class Recipe with public properties with get and set methods, now my Query class says recipeDataBase.Recipe'does not contain a definition for 'add' – Craig Smith Oct 19 '12 at 22:30
  • @CraigSmith: What is `add`? You don't need to add it to something. Just select it as shown above. Simplified example (without joins): `IEnumerable recipeInfo=from a in recipeDataSet.Recipe select new Recipe(){RecipeName=a.RecipeName, Nationality=a.Nationality, Event=a.Event};` – Tim Schmelter Oct 19 '12 at 22:34
  • hmmm, fixed the add problem now I'm back to Cannot implicitly...... are you missing a cast. – Craig Smith Oct 19 '12 at 22:35
  • @CraigSmith: Yes, you need to return the `IEnumerable` instead of the `IEnumerable`, so change the method signature. – Tim Schmelter Oct 19 '12 at 22:36
  • the problem is still with the select statment – Craig Smith Oct 19 '12 at 22:41
  • fixed, I needed to change the Ie – Craig Smith Oct 19 '12 at 22:42
  • fixed, I needed to change the type IEnuberable to IEnumberable. All new stuff to me, thank you for your help!! – Craig Smith Oct 19 '12 at 22:43
  • this is my first project that I'm trying more than just create a program, I'm trying to create a professional program. One that will be easier to support later. I learned about using classes and how to create them, but I always find it much easier to create 100 methods in one class. – Craig Smith Oct 19 '12 at 22:50
  • OOP is just experience, later you'll notice how much more reusable,maintainable,readable and extendable classes which appropriate properties and methods are. Your 100 methods you'll never use again, but if you split the functionality into 100 classes you'll reuse them later often. – Tim Schmelter Oct 19 '12 at 23:16
  • exactly, that's what I'm trying to do now, create more reusable code. My first program that I wrote with this recipe database was so long and convoluted that I decided now was the time to fix it. This is my first experience with linq to data, or linq in general. I made the porgram in 5 days for a job interview because I new that this was a big part of the job there. Had fun learning about datasources and linq, don't know if I'll get the job. – Craig Smith Oct 19 '12 at 23:22
0

You are using an anonymous type so this:

        var recipeInfo = (from a in recipeDataSet.Recipe
                                          from b in recipeDataSet.Rating
                                          from c in recipeDataSet.RecipeIngredient
                                          where a.RecipeName == recipeName &&
                                          a.RecipeNum == c.RecipeNum &&
                                          a.RatingNum == b.RatingNum
                                          select new { a.RecipeName, a.Nationality, a.Event, a.Source, b.FamilyRating, c.Ingredient }).ToList();

...Gives you an IEnumerable of an anonymous type with 6 values, possibly all strings. var doesn't stand for "variant" and is still a strongly-typed declaration, only it is resolved at compile-time (which will fail if the type can't be inferred from usage). Thus, the above code makes var mean IEnumerable<anonymous_type_with_6_strings> at compile-time, but the return statement attempts to make this IEnumerable<string> - this is where you're getting the compile-time cast exception.

I suggest you create a simple class to hold RecipeInfo values and so your method could return IEnumerable<RecipeInfo>:

class RecipeInfo
{
    public string RecipeName {get;set;}
    public string Nationality {get;set;}
    public string Event {get;set;}
    public string Source {get;set;}
    public string FamilyRating {get;set;}
    public string Ingredient {get;set;}
}

And then you can project your selection into this type:

    var recipeInfo = (from a in recipeDataSet.Recipe
                                      from b in recipeDataSet.Rating
                                      from c in recipeDataSet.RecipeIngredient
                                      where a.RecipeName == recipeName &&
                                      a.RecipeNum == c.RecipeNum &&
                                      a.RatingNum == b.RatingNum
                                      select new RecipeInfo{RecipeName=a.RecipeName, Nationality=a.Nationality, Event=a.Event, Source=a.Source, FamilyRating=b.FamilyRating, Ingredient=c.Ingredient }).ToList();
Mathieu Guindon
  • 69,817
  • 8
  • 107
  • 235