Why can't I get anything back when I use Linq to Sql Select? - asp.net-mvc

Could you please check my code? Why can't I get any values back when I use Linq to Sql?
BHS_TimeSheet is my database table in which have some records.
Model.TimeSheet is a class I create in the model.
Private db As DataFactoryDataContext
Public Sub New()
db = New DataFactoryDataContext
End Sub
Public Sub New(ByVal repository As DataFactoryDataContext)
db = repository
End Sub
Public Function GetTimeSheetByProject(ByVal wbs1 As String, ByVal wbs2 As String, ByVal wbs3 As String) _
As List(Of Model.TimeSheet) Implements ITimeSheetRepository.GetTimeSheetByProject
Return (From ts In db.BHS_TimeSheets _
Where ts.WBS1.Equals(wbs1) And ts.WBS2.Equals(wbs2) And ts.WBS3.Equals(wbs3) _
Select New Model.TimeSheet(ts.TSBatchNo, ts.Employee, ts.TransDate, ts.WBS1, ts.WBS2, ts.WBS3, ts.LaborCode, _
ts.RegHrs, ts.OvtHrs, ts.SpecialOvtHrs, ts.TransComment, ts.Status, ts.AuthorizedBy, _
ts.RejectReason, ts.ModDate)).ToList
End Function

Your Linq-to-SQL statement
(From ts In db.BHS_TimeSheets
Where ts.WBS1.Equals(wbs1)
And ts.WBS2.Equals(wbs2)
And ts.WBS3.Equals(wbs3) _
basically corresponds to this SQL query:
SELECT * FROM dbo.BHS_TimeSheets
WHERE WBS1 = (value for wbs1)
AND WBS2 = (value for wbs2)
AND WBS3 = (value for wbs3)
Does that SQL query return any values, if you call it with in SQL Server Management Studio using the same parameters for wbs1, wbs2, wbs3 as you do in your Linq-to-SQL code??
Update: okay, so the SQL query does return results - next step: approach the Linq-to-SQL stuff step by step. First, try this - do you get any results??
Dim basicQueryResults = (From ts In db.BHS_TimeSheets
Where ts.WBS1.Equals(wbs1)
And ts.WBS2.Equals(wbs2)
And ts.WBS3.Equals(wbs3)
).ToList();
Does your resulting list of items have a .Count > 0 or not??
If not: there must be something wrong with your Linq-to-SQL model then. Have you changed your database and not updated the DBML file?? Can you drop the DBML file and do it again - does it work now? Or do you still have the same results??

Related

Stored procedure returning dynamic columns in Entity Framework

I have a function calling a SQL Server stored procedure using Entity Framework 6.2.
The stored procedure returns a result set which has different number of columns on each call, and column names may vary on each call.
Function getListOfDocs() As JsonResult
Try
Using entities As PromatEntities = New PromatEntities()
Dim param(1) As SqlParameter
param(0) = New SqlParameter("#ProjID", SqlDbType.Int)
param(0).Value = vProjectId
Dim query = entities.Database.SqlQuery(Of "help required here")("sp_EIP_IPSSDocMaster_Get", param) // cannot handle this case as entity framework needs type
Dim lstDocs = query.ToList
End Using
Return Json(New With {lstDocs}, JsonRequestBehavior.AllowGet)
Catch ex As Exception
ClsCommon.ExceptionManager(ex)
Return Nothing
End Try
End Function
But Entity Framework doesn't allow anonymous types in database.SqlQuery. Can anyone suggest a way to solve the issue and get the anonymous type data to view?

Returning DbQuery to view that requires IEnumerable

The problem:
Exception Details: System.InvalidOperationException: The model item
passed into the dictionary is of type
'System.Data.Entity.Infrastructure.DbQuery`1[System.Int32]', but this
dictionary requires a model item of type 'migros.Models.State'.
What I'm trying to do
I need to pass the result of the following linq query to a View.
using (var db = new migros_mockEntities1())
{
var listOfIdeas = (from x in db.States select x.ID);
return View(listOfIdeas);
}
The View requires IEnumerable, but it seems I can't cast the result of the linq query to IEnumerable.
I'm using entity framework database first approach.
The problem is that you trying to return ObjectQuery from within the using block.
Try to materialize your object-set
var listOfIdeas = (from x in db.States select x.ID).ToList();
Also, dont forget, that dealing with context can be tricky.
In your case var listOfIdeas = (from x in db.States select x.ID) is just a query, that will run only when you'd begin to iterate over it. So, if context gets already disposed you'd get an exception, trying to use listOfIdeas.

Error: Cast System.Data.Objects.ObjectQuery

I'm trying to query my EF Model (using ASP.NET MVC WebApi) but only the first version (using SingleOrDefault) works and not the second one and i can't get my head around it!
Working:
Public Overloads Shared Function GetById(id As Integer) As MEDIA
Dim db As New EFEntities()
Dim r As New MEDIA()
r = db.MEDIA.SingleOrDefault(Function(p) p.id = id)
Return r
End Function
Not Working:
Error : Unable to cast object of type 'System.Data.Objects.ObjectQuery`1[Data.MEDIA]' to type 'Data.MEDIA'
Public Overloads Shared Function GetById(id As Integer) As MEDIA
Dim db As New EFEntities()
r = From media In db.MEDIA
Where media.id= id _
Select media
Return r
End Function
I would really appreciate it if somebody could show me how to get the second version running and explain what the problem is!
In your first example, the line:
r = db.MEDIA.SingleOrDefault(Function(p) p.id = id)
initializes a single MEDIA object.
In your second example, however, the line:
r = From media In db.MEDIA
Where media.id= id _
Select media
initializes a collection of MEDIA objects - incompatible types.
If you changed your return expression in your second example to:
Return r.SingleOrDefault()
and stick Dim in front of the initialization of r it'll work.

Getting only what is needed with Entity Framework

With a plain connection to SQL Server, you can specify what columns to return in a simple SELECT statement.
With EF:
Dim who = context.Doctors.Find(3) ' Primary key is an integer
The above returns all data that entity has... BUT... I would only like to do what you can with SQL and get only what I need.
Doing this:
Dim who= (From d In contect.Doctors
Where d.Regeneration = 3
Select New Doctor With {.Actor = d.Actor}).Single
Gives me this error:
The entity or complex type XXXXX cannot be constructed in a LINQ to Entities query.
So... How do I return only selected data from only one entity?
Basically, I'm not sure why, but Linq can't create the complex type. It would work if you were creating a anonymous type like (sorry c# code)
var who = (from x in contect.Doctors
where x.Regeneration == 3
select new { Actor = x.Actor }).Single();
you can then go
var doctor = new Doctor() {
Actor = who.Actor
};
but it can't build it as a strongly typed or complex type like you're trying to do with
var who = (from x in contect.Doctors
where x.Regeneration == 3
select new Doctor { Actor = x.Actor }).Single();
also you may want to be careful with the use of single, if there is no doctor with the regeneration number or there are more than one it will throw a exception, singleordefault is safer but it will throw a exception if there is more than one match. First or Firstordefault are much better options First will throw a exception only if none exist and Firstordefault can handle pretty much anything
The best way to do this is by setting the wanted properties in ViewModel "or DTO if you're dealing with upper levels"
Then as your example the ViewModel will be:
public class DoctorViewModel{
public string Actor {get;set;}
// You can add as many properties as you want
}
then the query will be:
var who = (From d In contect.Doctors
Where d.Regeneration = 3
Select New DoctorViewModel {Actor = d.Actor}).Single();
Sorry i wrote the code with C# but i think the idea is clear :)
You can just simply do this:
Dim who= (From d In contect.Doctors
Where d.Regeneration = 3
Select d.Actor).Single
Try this
Dim who = contect.Doctors.SingleOrDefault(Function(d) d.Regeneration = 3).Actor

Executing Method Against DataContext Returning Inserted ID

Is there any way to use DataContext to execute some explicit SQL and return the auto-increment primary key value of the inserted row without using ExecuteMethodCall? All I want to do is insert some data into a table and get back the newly created primary key but without using LINQ (I use explicit SQL in my queries, just using LINQ to model the data).
Cheers
EDIT: Basically, I want to do this:
public int CreateSomething(Something somethingToCreate)
{
string query = "MyFunkyQuery";
this.ExecuteCommand(query);
// return back the ID of the inserted value here!
}
SOLUTION
This one took a while. You have to pass a reference for the OUTPUT parameter in your sproc in your parameter list of the calling function like so:
[Parameter(Name = "InsertedContractID", DbType = "Int")] ref System.Nullable<int> insertedContractID
Then you have to do
insertedContractID = ((System.Nullable<int>)(result.GetParameterValue(16)));
once you've called it. Then you can use this outside of it:
public int? CreateContract(Contract contractToCreate)
{
System.Nullable<int> insertedContractID = null; ref insertedContractID);
return insertedContractID;
}
Take heavy note of GetParameterValue(16). It's indexed to whichever parameter it is in your parameter list (this isn't the full code, by the way).
You can use something like this:
int newID = myDataContext.ExecuteQuery<int>(
"INSERT INTO MyTable (Col1, Col2) VALUES ({0}, {1});
SELECT Convert(Int, ##IDENTITY)",
val1, val2).First();
The key is in converting ##IDENTITY in type int, like Ben sugested.
If you insist on using raw sql queries, then why not just use sprocs for your inserts? You could get the identity returned through an output parameters.
I'm not the greatest at SQL, but I broke out LinqPad and came up with this. It's a big hack in my opinion, but it works ... kinda.
DataContext.ExecuteQuery<T>() returns an IEnumerable<T> where T is a mapped linq entity. The extra select I added will only populate the YourPrimaryKey property.
public int CreateSomething(Something somethingToCreate)
{
// sub out your versions of YourLinqEntity & YourPrimaryKey
string query = "MyFunkyQuery" + "select Convert(Int, SCOPE_IDENTITY()) as [YourPrimaryKey]";
var result = this.ExecuteQuery<YourLinqEntity>(query);
return result.First().YourPrimaryKey;
}
You'll need to modify your insert statement to include a SELECT ##Identity (SQL Server) or similar at the end.

Resources