views:

243

answers:

1

Hey everyone, I had a couple of questions relating to the .NET Entity Framework and using stored procedures. Here goes:

  1. I know that we can right click a stored procedure and choose Function Import to be able to use with code. Is there a way to do this for many stored procedures at once?

  2. When doing a Function Import, I can create a new Complex type or use an existing Complex type. Well, how can I access Complex types/objects that are outside of the edmx file? That is, if I have a class in my project, is it possible to access it while doing a Function Import?

  3. When calling the stored procedure from code, it returns an IEnumerable of the Complex type I set it as. However, sometimes these complex types do not have all of the properties that I need, so I create a new class in my project that inherits from the complex type used in the stored procedure. Problem is, I can't seem to cast the complex type returned from the stored procedure to the new class I created. Any reason why I can't do this? What I ended up doing is looping through the IEnumerable and adding each item to a new list of the class that I created. But this feels and looks messy.

Bara

+2  A: 
  1. Maybe I'm misunderstanding, but in your model you can right-click > Update Model from Database. In the Add tab, simply select all the stored procedures you want to add to the model.

  2. Not as far as I know. The point of Entity Framework is to avoid having to create your entities manually (code generation). You either create your database first and copy to model or create model first and generate database tables. Either way, the actual .NET entities are generated automatically. If you later change your model, the entities are re-generated. If you could import your own pre-existing entities, you would risk having them overwritten when your model changes. They would also be outside the model's control (how to handle if they're in separate assemblies, etc?). With partial entities (more on that on #3), you can extend the generated classes without risking your customizations getting overwritten. You could still use your existing classes as DTOs, but then you would have to manually convert from the EF-generated entity to your DTO object.

  3. You can't cast a base class to a derived class. See: http://stackoverflow.com/questions/124336/a-way-of-casting-a-base-type-to-a-derived-type

I'm not sure about .NET 3.5 (EF 1), but entities/complex types in .NET 4 (EF 2) are partial classes. That means you can add members simply by extending the class. So for example, if your custom type was:

public partial class Address
{
  public string Address1 { get; set; }
  public string Address2 { get; set; }
  public string City { get; set; }
  public string State { get; set; }
  public string Zip { get; set; }
}

You could create a new file with:

public partial class Address
{
  public string MyProperty { get; set;}
}

Then do new Address { Address1 = "abc", MyProperty = "def" };. They'll both have to be in the same assembly and in the same namespace.

Nelson
1. After you've added the stored procedures, you still have to go to each one and do a Function Import. Right now I have to do this individually, and for hundreds of stored procedures this can get out of hand.2. I see, fair enough. Your answer to number 3 helps a lot with this though, so thank you.3. That doesn't exactly answer my question, but it's a huge help. I'm certain I can change my code to work with this instead. Thanks for all the help :)
Bara
I'm trying to use the partial class, and it's all working properly from a coding standpoint. However, I'm returning a list of the class as XML (using a REST service) and it's missing the parameters from my partial class (eg: MyProperty in your example). Any reason why?
Bara
Apparently, adding this above my property fixes it: [global::System.Runtime.Serialization.DataMemberAttribute()] ... eg, in your sample it would go right above public string MyProperty { get; set; }
Bara
@Bara: 1. I haven't used stored procedures much with EF, so I'm not very familiar with that. The only thing I can think of is modifying the model as XML (in VS, right-click, Open with..., XML Editor). You can edit directly, use search/replace, or even write an external script to modify it. But I'm not aware of anything built-in.
Nelson
@Bara: 3. "I can't seem to cast the complex type returned from the stored procedure to the new class I created [that inherits from the complex type]". The complex type returned would be the base class; your class is a derived class. The link explains why you can't cast a base class to a derived class... unless I'm still misunderstanding. Either way, looks like I got you headed in the right direction at least.
Nelson
@Bara: You should be able to add a `using System.Runtime.Serialization;` so that your properties would only need `[DataMemberAttribute()]` In fact, `Attribute` is implied and the parentheses are optional (if you don't have parameters), so you should be able to do `[DataMember]`.
Nelson
@Bara: Back to 1: There are a lot of opinions for and against stored procedures. If you don't use them, you gain a couple advantages. There is less manual work such as creating the SPs and setting them in the model. Generated SQL only updates changed columns. This could be significant if you have blob columns that don't need updating, but you could split this off into multiple SPs (even more work) to achieve a similar effect. My personal opinion is to use EF's SQL for most CRUD and use SPs for specific cases. However, I'm not going to tell you not to use them since there are some benefits.
Nelson
I agree that I could use EF's SQL for most of the work, but we already have stored procedures setup and I don't want to spend the time to "convert" them to EF LINQ calls. Also, I already figured out I could do that with the DataMember, I just figured I'd post the whole thing for anyone else that comes here looking for answers :) Finally, using Partial Classes resolved most of my issues. I was also able to reduce my code a bit due to this. Thanks for the help, I've got everything I need now :)
Bara