Inner Join in Entity Framework - how? - sql

I am new to Entity Framework and I have this SQL query:
SELECT
WarningTypes.WarningTypeID, WarningTypes.WarningDescription,
WarningTypes.WarningArDescription, WarningReasons.ReasonName
FROM
WarningTypes
INNER JOIN
WarningReasons ON WarningTypes.WarningReasonID = WarningReasons.ID
and I need to convert this to be entity frame work so I Wrote this vb.net code:
Public Function selectAllWarningTypes() As System.Linq.IQueryable
'Dim dt As New DataTable
'wt.selectAllWarningTypes(dt)
Dim query = _
From warningTypes In objSRSEntities.WarningTypes _
From warningReasons In objSRSEntities.WarningReasons _
.Where(Function(wr) wr.ID = warningTypes.WarningReasonID) _
Select warningTypes = warningTypes, warningReasons = warningReasons
Return query
End Function
The problem is: this run time error returned when I set result in gridview:
Data binding directly to a store query (DbSet, DbQuery, DbSqlQuery, DbRawSqlQuery) is not supported
Thanks.

Related

Linq join select all columns and CopyToDataTable

TABLE SCHEMA I'm having trouble solving a query in linq to dataset; I have to make a simple left join between two datatable but I do not know in advance the exact number of columns in the datatable B (A, B, C ...?) so I wanted to select all the columns; I found the following link
select-all-columns-after-join-in-linq
select-all-columns-for-all-tables-in-join-linq-join
Dim Query = From A In TableA _
Join B In TableB _
On A("COD") Equals B("COD") _
Select New With {A, B}
Dim TableC As DataTable = Query.CopyToDataTable()
I tried also
Select New With {.DAT = A.ItemArray.Concat(P.ItemArray).ToArray()}).ToList
and many more but i failed to bring the query result to a new datatable; I received type conversion errors or i did not understand how to bring the query result provided in two separate tables into one datatable.
Creating some extension methods and using Reflection will do what you want, though this may not be the ideal way to solve your issue (generally, Reflection never is).
Public Module SomeExt
<System.Runtime.CompilerServices.Extension()>
Public Function GetTypedValue(Of TProp)(ByVal p As PropertyInfo, obj As Object) As TProp
Return DirectCast(p.GetValue(obj), TProp)
End Function
<System.Runtime.CompilerServices.Extension()>
Public Function FlattenToDataTable(Of T)(src As IEnumerable(Of T)) As DataTable
Dim ans = New DataTable()
Dim srcdtpis = GetType(T).GetProperties().Cast(Of PropertyInfo)().ToList()
For Each aDT As DataTable In srcdtpis.Select(Function(pi) pi.GetTypedValue(Of DataRow)(src.First()).Table)
For Each col In aDT.Columns.Cast(Of DataColumn)()
ans.Columns.Add(col.ColumnName, col.DataType)
Next
Next
For Each drs In src
Dim newDR = ans.NewRow
For Each aDR In srcdtpis.Select(Function(pi) pi.GetTypedValue(Of DataRow)(drs))
For Each colname In aDR.Table.Columns.Cast(Of DataColumn)().Select(Function(dc) dc.ColumnName)
newDR(colname) = aDR(colname)
Next
Next
ans.Rows.Add(newDR)
Next
Return ans
End Function
End Module
You would use it as follows:
Dim Query = From A In TableA.AsEnumerable() _
Join B In TableB.AsEnumerable() _
On A("COD") Equals B("COD") _
Select New With {A, B}
Dim TableC As DataTable = Query.FlattenToDataTable()
Note that duplicate column names will be set to the last DataTable's value.

VB net & Mongo: Using where clause with LINQ causes error "Unsupported where clause: (Boolean)Operators.CompareObjectLess"

I have a collection in MongoDB and I'm using MongoDB Driver in VB net. I want to update several documents depending on a condition.
For this, I want to use LINQ, but the select causes an error and I don't know how to fix it.
Here's the code:
Dim update_for As UpdateBuilder
Dim query_for As IMongoQuery
Dim coll_for = db.GetCollection(Of MyClass)("collection_1")
Dim queryMun = (From a In coll_for _
Where (a.field_1 < 10000) _
Select a)
For Each emp In queryMun
query_for = Query.EQ("_id", emp.Id)
update_for = Update.Set("field_1", BsonValue.Create("0" + emp.field_1))
coll.Update(query_for, update_for, opts)
Next
When it executes de For Each sentence, it raises the exception: Unsupported where clause: (Boolean)Operators.CompareObjectLess(a.field_1, 10000, true).
What am I doing wrong?
Thank you very much for your help.
I think the error is clear:
You can't use a Less Than "<" operator in you WHERE clause because it's unsupported.
I have found a way to do this update based on the value of the attribute itself. What I want to do is add a "0" at the beginning of the attribute value, for example, if field_1=4567, after the update field_1='04567'.
Here's the code:
Dim update_for As UpdateBuilder
Dim query_for As IMongoQuery
Dim opts = New MongoUpdateOptions
opts.Flags = UpdateFlags.Multi
Dim coll_for = db.GetCollection(Of MyLINQClass)("collection_1")
Dim queryMun2 As New QueryDocument
Dim query_1 = Query.LT("field_1", MongoDB.Bson.BsonValue.Create(10000))
queryMun2.AddRange(query_1.ToBsonDocument)
Dim queryMun = coll_for.Find(queryMun2)
For Each emp In queryMun
query_for = Query.EQ("_id", emp.Id)
update_for = Update.Set("field_1", BsonValue.Create("0" + emp.FField_1.ToString))
coll.Update(query_for, update_for, opts)
Next
And here is the definition of MyLINQClass:
Public Class MyLINQClass
<BsonElementAttribute("_id")> _
Public Property Id() As ObjectId
<BsonElementAttribute("field_1")> _
Public Property FField_1() As Object
End Class

How do I return a single entity with a self-join using LINQ (in VB.NET)?

I am trying to return a single entity class ("category") with a LINQ query (in VB.NET) with a JOIN, but it isn't working. I think it's either because:
I'm getting an IEnumerable resultset (of 1) OR
I'm getting more than just the first-table-in-the-join's
columns back
because I get this invalid type cast exception:
Unable to cast object of type 'System.Data.Linq.DataQuery`1[category]'
to type 'category'.
Here is SQL that does what I want (note how I don't want any columns from the joined table):
select subcat.*
From category as cat
join category as parentcat On cat.cat_id = cat.parent_cat_id
Where parentcat.cat_url = 'dogs'
And cat.cat_url = 'poodles'
Here's the LINQ code I have that works in LINQPad:
dim q = From cat In categories _
Join parentcat In categories On parentcat.cat_id Equals cat.parent_cat_id _
Where parentcat.cat_url.ToLower = "dogs" _
And cat.cat_url.ToLower = "poodles" _
Select categories.SingleOrDefault(function(c) c.cat_id = cat.cat_id)
q.dumb
But this doesn't work in my "CategoryRepository" function in VB.NET:
Public Function GetCategoryByURL(ByVal strCatURL As String, ByVal strSubCatURL As String) As category Implements ICategoryRepository.GetCategoryByURL
Return From cat In db.categories _
Join parentcat In db.categories On parentcat.cat_id Equals cat.parent_cat_id _
Where parentcat.cat_url.ToLower = strCatURL.ToLower _
And cat.cat_url.ToLower = strSubCatURL.ToLower _
Select db.categories.SingleOrDefault(Function(C) C.cat_id = cat.cat_id)
End Function
How do I make it to return a single instance of the "category" class? (I need it that way because I have this same function overloaded that returns a single instance ... and that works!) I have verified that the database is correct and it should return the "poodles" category.
I'm new to LINQ, so I'm sure there is something very obvious that I'm doing incorrectly, so I'd appreciate any help!
You query categories and you return the statement db.categories.SingleOrDefault(Function(C) C.cat_id = cat.cat_id) for each row in the result set. This is always an IQueryable even though it may have 0 or 1 results. You must do SingleOrDefault() over the whole query:
Dim query = From cat In db.categories _
Join parentcat In db.categories On parentcat.cat_id
Equals cat.parent_cat_id _
Where parentcat.cat_url.ToLower = strCatURL.ToLower _
And cat.cat_url.ToLower = strSubCatURL.ToLower _
Select cat
Return query.SingleOrDefault()

Linq union for extra row not from table

VB examples please
I need to return the same results from linq as I get using SQL
SELECT DISTINCT Area, Region
FROM dbo.Regions
Union
SELECT null,'All'
Order by 1,2
I use this for showing an "All" selecting in a combo box
My current linq points to a view that does the union for me but I want to know how to do it right in linq. I can't figure out how to union a row for the null,'All' values.
Public Shared Function GetRegions(ByVal Area As String) As IEnumerable
Dim DB As New SiteDBDataContext
Return From values In DB.uv_Areas _
Where values.Area = Area Or Area = "" Or values.Area Is Nothing _
Order By values.Region _
Select values.Area, values,Region
End Function
Thanks
You can't do it in the DB with Linq to SQL or Entity Framework, but you can do it in memory with Linq to Objects:
Public Shared Function GetRegions(ByVal Area As String) As IEnumerable
Dim DB As New SiteDBDataContext
Dim query = _
From values In DB.uv_Areas _
Where values.Area = Area Or Area = "" Or values.Area Is Nothing _
Order By values.Region _
Select New With { values.Area, values.Region }
Dim all = { New With { .Area = DirectCast(Nothing, String), .Region = "All } }
Return all.Concat(query)
End Function

JQGrid on ASP.Net MVC with VB.Net

I am trying to make a JQGrid for a simple table.
After following through with a VB translated version from
http://haacked.com/archive/2009/04/14/using-jquery-grid-with-asp.net-mvc.aspx
from
http://www.qa.downappz.com/questions/jqgrid-sorting-in-vb-net-mvc-app.html
I modified it to my own database and came up with this function
Public Function SelectGridData(ByVal sidx As String, ByVal sord As String, ByVal page As Integer, ByVal rows As Integer) As ActionResult
Dim context As New IssueDBEntities
Dim pageIndex As Integer = Convert.ToInt32(page) - 1
Dim pageSize As Integer = rows
Dim totalRecords As Integer = context.Issues.Count()
Dim totalPages As Integer = CInt(Math.Ceiling(CSng(totalRecords) / CSng(pageSize)))
Dim jsonData = New With { _
.total = totalPages, _
.page = page, _
.records = totalRecords, _
.rows = (From p In context.Issues _
Order By (p.ID & " " & sord) _
Select New With {.id = p.ID, .cell = _
{p.ID, p.Image_Path, p.Magazine_Type,p.Magazine_Path}}).ToArray()}
Return Json(jsonData, JsonRequestBehavior.AllowGet)
End Function
The grid does show up without any data, and the system throws an error
The error description says
"Unable to cast the type 'System.Int32' to type 'System.Object'. LINQ to Entities only supports casting Entity Data Model primitive types."
Any help is appreciated, if this is due to some basic misunderstanding, please guide me, I am willing to do some hard work.
Thank you
Edit: The code that finally worked as per Oleg's Suggestion
Dim Simple_Object As IQueryable(Of Object)
Dim Second_Simple_Object As IQueryable(Of Object)
Dim My_Array As Array
Dim My_Second_Array As Array
Simple_Object = From p In Context.Issues _
Order By (p.ID & " " & sord) _
Select New With {p.ID, p.Image_Path, p.Magazine_Type, p.Magazine_Path}
My_Array = Simple_Object.ToArray()
Second_Simple_Object = From p In Context.Issues _
Order By (p.ID & " " & sord) _
Select New With {p.ID}
My_Second_Array = Second_Simple_Object.ToArray()
Dim My_Result(0) As My_Record_Type
For i = 0 To My_Array.GetLength(0) - 1
If i > 0 Then
ReDim Preserve My_Result(i)
End If
My_Result(i) = New My_Record_Type
My_Result(i).id = CInt(My_Second_Array(i).ID)
My_Result(i).Cell = {My_Array(i).ID.ToString, My_Array(i).Image_Path.ToString, _
My_Array(i).Magazine_Type.ToString, My_Array(i).Magazine_Path.ToString}
Next
Class My_Record_Type
Public id As Integer
Public Cell As String()
End Class
You try to fill rows property in one step. The problem is that you use Entity Framework which have some restrictions in the conversion of the data types. You can solve the problem if you first make query to get the items which you need without any data conversion and save intermediate results as List of items. After that you can make another LINQ Query where you include explicit conversion of p.ID to string. Moreover your current code don't use any paging of data. So the user will never seen more as the first page if you don't use loadonce: true.
It's difficult for me to write correct code in VB without debugging it. I use C# instead since last years. I recommend you to look at the answer for more information. It contains implementation of the server side filtering. If you don't need it and remove the corresponding code the rest code will be very short and I hope it will be easy to understand.
Here is complete sample of JQgrid with ASP.NET MVC 3 + C# (you can convert it to vb.net)
http://www.dotnetacademy.blogspot.in/2012/04/using-jqgrid-in-aspnet-mvc-3.html