I"m using VS 2010 & EF 3.5. I've imported a stored procedure which returns a list of guids using the Function Import feature. How do I invoke it in my code? After instantiating the dbcontext, intellisense doesn't display the procedure I've imported. I know it's pretty easy in EF 4.0 but I'm stuck with EF 3.5 for this project. Any ideas on how get around this other than doing it the old-fashioned way?
I don't think EF versions prior to 4 can use imported stored procedures that don't return entities. That is, your stored procedure must return a complete entity object in order for EF to use it. Since your procedure only returns a list of GUIDs, EF doesn't know how to use it.
You can put this in your partial data-context class to call the procedure:
public IEnumerable<Guid> GetMyGUIDs()
{
if (this.Connection.State != System.Data.ConnectionState.Open)
this.Connection.Open();
var command = new System.Data.EntityClient.EntityCommand
{
CommandType = System.Data.CommandType.StoredProcedure,
CommandText = #"YourContext.YourProcedureName",
Connection = (System.Data.EntityClient.EntityConnection)this.Connection
};
var list = new List<Guid>();
using (var reader = command.ExecuteReader())
{
// get GUID values from the reader here,
// and put them in the list
reader.Close();
}
return list;
}
Related
Is it possible with Entity Framework code-first approach to map already created stored procedures?
For example I have a complex stored procedure and I want to map it with code first approach.
I will run the script for creating stored procedure using migration so the procedure will always available but how to map it with code first approach?
AFAIK, there's no built-in support to map the stored procedure in code-first. You have to manually call the procedure though you can map the results of the procedure using ObjectContext's Translate method.
E.g.
using (var db = new BloggingContext())
{
// If using Code First we need to make sure the model is built before we open the connection
// This isn't required for models created with the EF Designer
db.Database.Initialize(force: false);
// Create a SQL command to execute the sproc
var cmd = db.Database.Connection.CreateCommand();
cmd.CommandText = "[dbo].[GetAllBlogsAndPosts]";
try
{
db.Database.Connection.Open();
// Run the sproc
var reader = cmd.ExecuteReader();
// Read Blogs from the first result set
var blogs = ((IObjectContextAdapter)db)
.ObjectContext
.Translate<Blog>(reader, "Blogs", MergeOption.AppendOnly);
foreach (var item in blogs)
{
Console.WriteLine(item.Name);
}
// Move to second result set and read Posts
reader.NextResult();
var posts = ((IObjectContextAdapter)db)
.ObjectContext
.Translate<Post>(reader, "Posts", MergeOption.AppendOnly);
foreach (var item in posts)
{
Console.WriteLine(item.Title);
}
}
finally
{
db.Database.Connection.Close();
}
}
You can also map the stored procedure that returns more complex type, if you're using an .EDMX file. See this MSDN article for more details.
Note: you can add T4 template to add the custom mapping to add the custom stored procedure mapping every time the .EDMX is generated.
I have a table with nvarchar field (MS SQL Server 2008 R2). For testing, this code works fine:
Update [Screenshots] set name=N'Значение' where id=230246
right now I created Entity Framework model, I have set Unicode as True
then I try to update my record:
public void Put(FormDataCollection formData)
{
string filename = formData.Get("filename");
var screenshot = c.Screenshots.Where(p => p.filename == filename).FirstOrDefault();
if (screenshot != null)
{
screenshot.name = formData.Get("description");
c.SaveChanges();
}
}
but I got "?????" instead of unicode value. How to do it? I know about AsNonUnicode method, but this method works only for LINQ.
Are you sure that formData.Get("description") returns UTF-8 string (that it isn't converted somewhere)?
What is your approach in entity framework? Code-first/Design-first/Database-first?
Try to remove database and recreate - remove database and then in designer right click -> Generate database from model...
Get Entity Framework Profiler from Nu-get package manager and see what query is sending to database.
I'm using EF in my MVC project. In my project I need to use stored procedures. My problem is to use output parameter with stored procedures. I have no idea how to do that
When you create your entity model, you should make sure that you include stored procedures. Then, create Function Imports for them:
Open your Entity Model in Visual Studio
The Model Browser should open on the right side of the screen
In the Model Browser, you need to select the stored procedure and click Add Function Import to create the function for the stored procedure.
A dialog box will open to select the stored procedure and return type
That's it. Now you can use that in code.
using (MyEntities myContext = new MyEntities ())
{
System.Data.Objects.ObjectParameter output = new System.Data.Objects.ObjectParameter("OutputParameterName", typeof(int));
myContext.GetCustomerCount(output);
Console.WriteLine(output.Value);
}
Modified Answer for Entity Framework 6.x / VS 2015 - notice the namespace change:
using (MyEntities myContext = new MyEntities ())
{
System.Data.Entity.Core.Objects.ObjectParameter output = new System.Data.Entity.Core.Objects.ObjectParameter("OutputParameterName", typeof(int));
myContext.GetCustomerCount(output);
Console.WriteLine(output.Value);
}
Here is another way of doing it using Entity framework
YourDB db = new YourDB();
public double GetCategoryYearly(double Param1, double Param2, double Param3)
{
System.Data.Entity.Core.Objects.ObjectParameter OutputParam = new System.Data.Entity.Core.Objects.ObjectParameter("SPOutputParam", typeof(double));
var objStoredProc = db.YourStoredProc(Param1, Param2, Param3, OutputParam).First();
return Convert.ToDouble(OutputParam.Value);
}
using System.Data.Entity.Core.Objects;
using (Entities context = new Entities())
{
ObjectParameter output = new ObjectParameter("varName", typeof(int));
context.storedProcedure(output);
Console.WriteLine(output.Value.ToString());
}
I am stating out with entity framework. I have created my ADO.NET Entity Model and mapped the entities to a local SQL CE database file (all done via the wizards). I have created a unit test to test the data access and see how things work. The test executes fine and without any exceptions. However, no new row is generated in the database. Please Help!!!
public void TestCreateRelationshipType()
{
using (var c = new TenderModelEntities())
{
IList<RelationshipType> types = c.RelationshipTypes.ToList<RelationshipType>();
int num1 = types.Count();
RelationshipType type = new RelationshipType();
type.Description = "New Client";
c.AddToRelationshipTypes(type);
c.SaveChanges();
IList<RelationshipType> types2 = c.RelationshipTypes.ToList<RelationshipType>();
int num2 = types2.Count();
Assert.AreEqual(num1 + 1, num2);
}
}
New row is added to the database because you call the SaveChanges() function. When you call this on your datacontext, the changes are passed on to the database.
If you don't want to make any changes to the database, just comment out this section like below
// c.SaveChanges();
I understand stored procedures mapping is not supported by my understanding is that I should be able to call stored procedures.
I have quite a few complex stored procedures and with the designer I could create a complex type and I was all good.
Now in code first let's suppose I have the following stored procedure, just put together something silly to give an idea. I want to return a student with 1 address.
In code I have A Student and Address Entity. But no StudentAddressEntity as it's a link table.
I have tried the following but I get an error
Incorrect syntax near '."}
System.Data.Common.DbException {System.Data.SqlClient.SqlException}
ALTER Procedure [dbo].[GetStudentById]
#StudentID int
AS
SELECT *
FROM Student S
left join StudentAddress SA on S.Studentid = sa.studentid
left join Address A on SA.AddressID = A.AddressID
where S.StudentID = #StudentID
C# code:
using (var ctx = new SchoolContext())
{
var student = ctx.Database.SqlQuery<Student>("GetStudentById,#StudentID",
new SqlParameter("StudentID", id));
}
Any examples out there how to call sp and fill a complexType in code first, using out parameters etc.. Can I hook into ADO.NET?
Trying just an SP that returns all students with no parameters I get this error
System.SystemException = Cannot create a value for property
'StudentAddress' of type
'CodeFirstPrototype.Dal.Address'. Only
properties with primitive types are
supported.
Is it because I have in a way ignore the link table?
Any suggestions?
I believe that your exception actually is:
Incorrect syntax near ','.
because this is invalid statement: "GetStudentById,#StudentID". It should be without comma: "GetStudentById #StudentID".
The problem with stored procedures in EF is that they don't support loading navigation properties. EF will materialize only the main entity and navigation properties will not be loaded. This is solved for example by EFExtensions. EFExtensions are for ObjectContext API so you will have to check if it is also usable for DbContext API.
Using EFExtentions it will look something like
using (var context = new SchoolContext())
{
var command = context.CreateStoreCommand("GetStudentById", CommandType.StoredProcedure,
new SqlParameter("StudentID", id));
using (command.Connection.CreateConnectionScope())
using (var reader = command.ExecuteReader())
{
// use the reader to read the data
// my recommendation is to create a Materializer using EFExtensions see
// http://blogs.msdn.com/b/meek/archive/2008/03/26/ado-entity-framework-stored-procedure-customization.aspx
// ex
var student = Student.Materializer.Materialize(reader).SingleOrDefault();
return student;
}
}