I create a simple stored procedure with some joins with the customer table and other related tables, which takes in two parameters. I can execute this SP in SQL and works.
I drag and drop this SP to my DBML file and recompile.
I add the below code in order to call the SP and return it in a List
public IQueryable<Entities.Customer> AllCustomerRanges(int CId, int ItemID)
{
List<Entities.Customer> c = myDataContext.spCustomerRanges(CId, ItemID).ToList();
}
This gives me the error:
Cannot implicitly convert type 'System.Collections.Generic.List< spCustomerRangesResult>' to 'System.Collections.Generic.List< Entities.Customer>'
Now i dont have a class spCustomerRangesResult but after some research I'm puzzled if i have done something wrong or if i need to implement a class with all the properties that the Customer class has (which sounds a little long winded) or if i've just made an error.
Any idea of how i can call a SP which shows the data in a List?
new class spCustomerRangesResult automatically generated based on sp result, you should convert it to Entities.Customer like this:
public IQueryable<Entities.Customer> AllCustomerRanges(int CId, int ItemID)
{
var c = myDataContext.spCustomerRanges(CId, ItemID).ToList();
if (c == null)
return null;
var customers = c.Select(a => new Entities.Customer
{
FirstName=a.spResultFirstName,
LastName = a.spResultLastName
//this just example conversion, change it as needed.
});
return customers;
}
please note, that I return IQueryable even though the approach that you take when using ToList() but yet returning IQuerybale may not be needed. I dont know all details so this only to show how to convert but the whole method may need re-factoring.
Related
I have a stored procedure:
ALTER PROCEDURE [dbo].[GetAllAnnouncements]
AS
BEGIN
SELECT
Description, DisplayStartDate, DisplayEndDate
FROM
Announcements
END
I am trying to call the stored procedure and return it as array, but I get an error:
Cannot implicitly Convert Type MyProject.Models.GetAllAnnouncements_Result[] to string[]
My code:
public string[] getAllAnnouncements()
{
using (PerformanceReviewEntities objContext = new PerformanceReviewEntities())
{
var ann = objContext.GetAllAnnouncements();
string[] DisplayAnn = ann.ToArray();
}
}
I know it has to do something within the edit function import, but I am just not sure what to do. I want to be able to run from home controller, and view it in my .cshtml page.
The function import is returning a collection of objects of type Announcements.
When you call this:
var ann = objContext.GetAllAnnouncements();
ann is a collection of objects, not strings.
Doing this:
string[] DisplayAnn = ann.ToArray();
Wil fail because you are trying to assign an array of objects to an array of strings.
You could do this instead, assuming you are interested in more than one column:
IEnumerable<Announcements> result = ann.ToArray();
And change the signature of your method to return the enumerable:
public IEnumerable<Announcements> getAllAnnouncements()
The call to ToArray() is done to force loading of the results. You don't have to cast it to an array if lazing loading is fine for you. Some people have trouble with that when they try to consume the enumeration after the connection to the database has been closed (e.g. the context is disposed).
In an MVC 5 web app using Entity Framework, I learned how to populate an Index view by using db.Database.SqlQuery<model> to execute a stored procedure and show the results in the Index View.
This is the relevant code in my Index View (and it works).
// supply parameter values required by the stored procedure
object[] parameters = {
new SqlParameter("#campus",SqlDbType.NVarChar,3) {Value=vm.SelectedCampus},
new SqlParameter("#date1",SqlDbType.DateTime) {Value=Convert.ToDateTime(vm.SelectedStartDate)},
new SqlParameter("#date2",SqlDbType.DateTime) {Value=Convert.ToDateTime(vm.SelectedEndDate)}
};
// populate the list by calling the stored procedure and supplying parameters
IEnumerable<PerfOdomoeterDate> query =
db.Database.SqlQuery<PerfOdomoeterDate>("PerfOdomoeterDate #campus, #date1, #date2",
parameters).OrderBy(m => m.StudentName).ToList();
And to put that code into better context, here is the entire Index ActionResult.
private PerformanceContext db = new PerformanceContext();
private static readonly string d1 = DateTime.Now.ToShortDateString();
private static readonly string d2 = DateTime.Now.ToShortDateString();
[HttpGet]
public ActionResult Index(int? page, string SelectedCampus = "CRA", string SelectedStartDate=null, string SelectedEndDate=null)
{
int PageNumber = (page ?? 1);
PerfOdomoeterDateViewModel vm = new PerfOdomoeterDateViewModel();
vm.SelectedCampus = SelectedCampus;
vm.SelectedStartDate = string.IsNullOrEmpty(SelectedStartDate) ? d1 : SelectedStartDate;
vm.SelectedEndDate = string.IsNullOrEmpty(SelectedEndDate) ? d2 :SelectedEndDate;
vm.CampusList = StaticClasses.ListBank.CampusList();
// supply parameter values required by the stored procedure
object[] parameters = {
new SqlParameter("#campus",SqlDbType.NVarChar,3) {Value=vm.SelectedCampus},
new SqlParameter("#date1",SqlDbType.DateTime) {Value=Convert.ToDateTime(vm.SelectedStartDate)},
new SqlParameter("#date2",SqlDbType.DateTime) {Value=Convert.ToDateTime(vm.SelectedEndDate)}
};
// populate the list by calling the stored procedure and supplying parameters
IEnumerable<PerfOdomoeterDate> query =
db.Database.SqlQuery<PerfOdomoeterDate>("PerfOdomoeterDate #campus, #date1, #date2",
parameters).OrderBy(m => m.StudentName).ToList();
vm.CreditTable = query.ToPagedList(PageNumber, 25);
return View(vm);
}
As I stated, this code works perfectly in the Index View. However, in a separate ActionResult, where the user has an option to export the data set to an Excel file, I use the same code, and I get this runtime error:
The SqlParameter is already contained by another SqlParameterCollection.
I was under the impression that each ActionResult is in its own scope, so how is it that I am getting this error when I am calling up a new query from a separate ActionResult?
Intellisense did not give me any clues as to how I could explicitly empty the parameters after executing the stored procedure.
This is the code in the ActionResult that is producing the error.
public ActionResult ExportToExcel(string SelectedCampus, string SelectedStartDate, string SelectedEndDate)
{
object[] parameters2 = {
new SqlParameter("#campus",SqlDbType.NVarChar,3) {Value=SelectedCampus},
new SqlParameter("#date1",SqlDbType.DateTime) {Value=Convert.ToDateTime(SelectedStartDate)},
new SqlParameter("#date2",SqlDbType.DateTime) {Value=Convert.ToDateTime(SelectedEndDate)}
};
IEnumerable<PerfOdomoeterDate> query =
db.Database.SqlQuery<PerfOdomoeterDate>("PerfOdomoeterDate #campus, #date1, #date2",
parameters2).OrderBy(m => m.StudentName).AsEnumerable();
...
The ADO.Net objects (like SqlParameter, SqlCommand etc.) presented to us by the .Net framework are a mere layer on top of the real stuff under the hood that is managed by the .Net connection pool. If we create a new SqlConnection —which is implicitly done by db.Database.SqlQuery— we don't really establish a new connection to the database. That would be far too expensive. In reality, our connection object "plugs" in to an available connection in the connection pool.
Normally, this mechanism is pretty transparent, but it is unveiled in issues like the one you see here. I remember having experienced similar issues (exceptions that persisted longer than met the eye).
The message is: you can't beat it, so join it. The quick solution seems to be renaming the parameters in one of the methods. A better solution, of course, is to factor out the repetitive part of your code into a method that contains the identical parts.
I would say, This is how as per the design.
You need to extract the data right from there .ToArray() or .ToList() etc...
Do not try to re execute the query for further data operations.
How can I call a scalar function in entity framework 6 ?
I have tried the following code
using (MhEntities DContext = new MhEntities())
{
var Account_IdParameter = Account_Id.HasValue ? new ObjectParameter("Account_Id", Account_Id) : new ObjectParameter("Account_Id", typeof(long));
string res = ((IObjectContextAdapter)DContext).ObjectContext.CreateQuery<string>("MoneyforHealthEntities.Fn_LEVEL0_Acount_Id", Account_IdParameter).FirstOrDefault();
return Convert.ToInt64(res);
}
No need to use ObjectContext to do this. Also, I don't think you can simply pass in the name of the function, you need to give it complete, valid SQL.
So I would try something like this instead:
using (MhEntities DContext = new MhEntities())
{
string res = DContext.Database.SqlQuery<string>("SELECT MoneyforHealthEntities.Fn_LEVEL0_Acount_Id(#p0)", Account_Id).FirstOrDefault();
return Convert.ToInt64(res);
}
Since you didn't give any details about which database you are using, or the exact function definition, it's possible that the above may need further tweaking. But it should at least give you the basic idea.
DateTime ServerTime = new ContextDbEntities().Database.SqlQuery<DateTime>("Select getdate();").FirstOrDefault();
MessageBox.Show(ServerTime.ToString());
All the answers right but if someone uses a stored procedure, it needs to be edit on function import by:
1. Right-click on your function then click on edit.
2. On the edit function Import window.
3. Select Scaler on the returns a collection section.
4. Finally, click ok and save your model.
In my example, I call an Insert stored procedure that returns a string value.
using (DbModel db = new DbModel())
{
string result = db.storedprocedureName(value1,value2).FirstOrDefault();
return result;
}
This seems like it should be straightforward, but I can't figure out how to make it work. Imagine the following models:
public class ModelA
{
public string Code {get;set;}
}
public class ModelB
{
public string Code {get;set;}
}
I am reading a set of ModelA out of a database, and I also need to grab ModelB based on the Code. The kicker is I need to match only a part of the code.
For example, ModelA the code might be "1234.00" and ModelB the code might be "001234.20" -- I want to link the two models based on both codes containing the 1234 part. I would prefer it to be a join, but I don't see how that's possible, so iterating through the first data set and matching them is fine too, but I still can't make that work.
I created a string extension method called TruncateCode, which will give me the part that I want, but LINQ doesn't seem to support calling extensions within a comparison or join (throws an exception complaining the method is unrecognized and can't be used). This is basically what I was attempting:
var query = a in db.ModelASet
(where clause)
select a;
foreach(ModelA item in query)
{
var query2 = b in db.ModelBSet
where b.Code.TruncatedCode() == item.Code.TruncatedCode() // this doesn't work :(
select b;
}
Dear reader, how would you approach this?
(INB4 "Why is your data laid out like this?" - This is a legacy database from over 10 years ago man, I'm just trying to get this to work.)
You need to materialize the results using ToList() or something similar in order to use your extension method.
var list = (a in db.ModelASet
select a).ToList();
foreach(var item in list)
{
var query2 = b in list
where b.Code.TruncatedCode() == item.Code.TruncatedCode() // this doesn't work :(
select b;
}
I wanted to use linq as so:
MyDBEntities context = new MyDBEntities();
context.MyTable.Where(i => MyMethod(i.column, valueToTest).ToList();
with
public bool MyMethod(Object a, Object b)
but apparently using such a method with isn't possible
so I was hopping I could use the methode in a stored procedure I would be able to call with linq
do you think is it possible ?
Generally it is possible to create C# function and use it in SQL Server (2005 and newer) but it is not so simple - you must use SQL CLR which means separate project for your function, special references, special types, etc. At last you must deploy the assembly to SQL server to be able to use the function in SQL. General documentation also covering how to create custom function:
Creating SQL Server Objects in Managed Code
Once you have your function on SQL server you can use it within stored procedure and you can use it within query. I'm actually not sure if you can import these functions into Linq-to-sql or EF model and use them in Linq-to-sql or Linq-to-entities queries.
Take a look here for a complete sample:
Calling custom methods in LINQ-to-SQL
I hope I understand you correctly.
Let's say that MyTable is a database table that contains the columns Name, and Address
Here's how you would get a value back whether the results contain the specified value you passed.
public void SomeMethod()
{
MyTable table= new MyTable();
bool b= MyMethod(table.Name, "Fred");
if(b)
//Do something
else
//Do something else
}
public bool MyMethod(MyTable a, object value)
{
using(var context= new MyDBEntities())
{
return context.MyTable.Where(i => a == value).Any();
}
}
This is what the database table 'MyTable' looks like behind the scenes.(the data context generated this)
public class MyTable
{
public string Name { get; set; }
public string Address { get; set; }
}
So you can see in the first method I pass table.Name to MyMethod, that's only possible because MyTable has a pubic property called Name. Also notice that we are using type Object for the value, as the parameter could an int, a string, a date time, who knows.
Note: This is untested code, but should get off to right track if I understand you correctly.