Entity Framework Metadata LINQ (Converting from C# to VB.NET) - linq

I've got a query in C# that is working for me to query the metadata for the Entity Framework. I need to convert it to VB.NET, but I'm struggling to convert the AS keyword to "cast" meta to System.Data.Metadata.Edm.EntityType. I've tried TryCast, CType, Cast, etc.
Here's the query in C#:
var queryResult = from meta in oc.MetadataWorkspace.GetItems(System.Data.Metadata.Edm.DataSpace.CSpace)
.Where(m => m.BuiltInTypeKind == System.Data.Metadata.Edm.BuiltInTypeKind.EntityType)
from p in (meta as System.Data.Metadata.Edm.EntityType).Properties
.Where(p => p.DeclaringType.Name == entityClassType.Name
&& p.Name == propertyName)
select p;
This is the closest I've come to getting it to compile in VB.NET (the As keyword in underlined and says ')' expected:
Dim query2 = _
From meta In entityObjectContext.MetadataWorkspace.GetItems(System.Data.Metadata.Edm.DataSpace.CSpace) _
.Where(Function(m) m.BuiltInTypeKind = System.Data.Metadata.Edm.BuiltInTypeKind.EntityType) _
From p In (meta As System.Data.Metadata.Edm.EntityType).Properties _
.Where(Function(p) p.DeclaringType.Name = entity.GetType().Name _
And p.Name = propertyName) _
Select p
This is killing me. I'm so close...

You can use CType to type cast:
...
From p In CType(meta, System.Data.Metadata.Edm.EntityType).Properties _
...
Update: Looking again at the query, I would suggest using OfType() instead:
From meta In entityObjectContext.MetadataWorkspace.GetItems(System.Data.Metadata.Edm.DataSpace.CSpace) _
.OfType(Of System.Data.Metadata.Edm.EntityType)() _
From p In meta.Properties _
Where p.DeclaringType.Name = entity.GetType().Name _
And p.Name = propertyName _
Select p
Update 2: Also, it looks like GetItems() has a generic version that I suspect will return only items of your desired type:
From meta In entityObjectContext.MetadataWorkspace.GetItems(Of System.Data.Metadata.Edm.EntityType)(System.Data.Metadata.Edm.DataSpace.CSpace) _
From p In meta.Properties _
Where p.DeclaringType.Name = entity.GetType().Name _
And p.Name = propertyName _
Select p

If I were writing this query in VB.NET, I would do it like this without the lambdas. I think it's easier to read, but they way you're doing it would probably be easier for a C# developer to read.
Dim query2 = _
From meta In entityObjectContext.MetadataWorkspace.GetItems(System.Data.Metadata.Edm.DataSpace.CSpace) _
Where m.BuiltInTypeKind = System.Data.Metadata.Edm.BuiltInTypeKind.EntityType _
From p In CType(meta, System.Data.Metadata.Edm.EntityType).Properties _
Where p.DeclaringType.Name = entity.GetType().Name _
And p.Name = propertyName) _
Select p

Related

vb.net Linq statement to c#

I am trying to convert this statement in vb.net Linq:
Dim exchangeTradingCapacity = (
From ts In db_context.TRADE_SUMMARies _
Join el In db_context.EXECUTION_LISTs On ts.TRADE_ID Equals el.TRADE_ID _
And ts.TRADE_PART_INDEX Equals el.TRADE_PART_INDEX _
And ts.VERSION Equals el.TRADE_VERSION _
Join oe In db_context.ORDER_EXECUTIONs On oe.EXECUTION_ID Equals ts.CONTRIBUTOR_REF _
Where rootOrdersToInclude.Distinct.Contains(el.ROOT_ORDER_ID) _
And el.TRADE_VERSION = (From el1 In db_context.EXECUTION_LISTs _
Where el1.TRADE_ID = el.TRADE_ID _
And el1.TRADE_PART_INDEX = el.TRADE_PART_INDEX _
And el1.ROOT_ORDER_ID = el.ROOT_ORDER_ID _
Select el1.TRADE_VERSION).Max() _
Group oe By Key = oe.EXCHANGE_TRADING_CAPACITY Into Group _
Select Key
).ToList
My attempt to convert it to c# has thus far been unsuccessful:
var exchangeTradingCapacity =
(from ts in dbContext.TRADE_SUMMARies
join e1 in dbContext.EXECUTION_LISTs on
new
{
ts.TRADE_ID,
ts.TRADE_PART_INDEX,
ts.VERSION
}
equals
new
{
e1.TRADE_ID,
e1.TRADE_PART_INDEX,
VERSION = e1.TRADE_VERSION
}
join oe in dbContext.ORDER_EXECUTIONs on ts.CONTRIBUTOR_REF equals oe.EXECUTION_ID
where rootOrdersToInclude.Distinct().Contains(e1.ROOT_ORDER_ID) &&
e1.TRADE_VERSION == (from el1 in dbContext.EXECUTION_LISTs
where el1.TRADE_ID == el.TRADE_ID &&
el1.TRADE_PART_INDEX == el.TRADE_PART_INDEX &&
el1.ROOT_ORDER_ID == el.ROOT_ORDER_ID
select el1.TRADE_VERSION).Max()
group oe by oe.EXCHANGE_TRADING_CAPACITY into theKey
select theKey
).ToList();
It appears that for some reason, 'el' is out of scope when inside the subquery. Can someone point me to the error of my ways? It seems like this should work.
You don't have an alias el (letter L), only the alias e1 (number 1).

linq union group by undefined

I am calling the following function from a web service but can't get the object defined.
Dim x = (From a In _db.report _
Select ep = a.CurrentReport, CuCy = a.Current_Cycle) _
.Union _
(From b In _db.Counts _
Group b By b.Year, b.Report Into k() _ <--------(this is undefined)
Select ep = b.Report, CucY = b.Year).ToList().Take(10)
Is this the correct way to do a group by in a union query?
I would appreciate any help.
The Grouping syntax in VB is slightly different than C#. The Group By requires you to state Into Group rather than aliasing the new structure. See if the following works for you:
Dim x = (From a In _db.report _
Select ep = a.CurrentReport, CuCy = a.Current_Cycle) _
.Union _
(From b In _db.Counts _
Group By b.Year, b.Report Into Group _ <--------(this is undefined)
Select ep = Key.Report, Key.Year).ToList().Take(10)
Since you don't appear to be aggregating in the second query, you might be able to just do a distinct instead:
From b in _db.Counts
Select b.Report, B.Year
Distinct

Finding nodes with "missing" attributes

I have xml that looks like this:
<Doc>
<Thing>
<ID type="One">Fred</ID>
</Thing>
<Thing>
<ID>Bill</ID>
</Thing>
<Thing>
<ID type="Two">John</ID>
</Thing>
</Doc>
I can write LINQ to find the type="One" nodes. (or type="Two")
Dim ThingList As IEnumerable(Of XElement) = _
From el In doc...<Thing>.<ID> _
Where el.Attribute("type").Value = "One" _
Select el
How would I write a linq query to find the ID node that doesn't have a type attribute at all?
You should use the fact that Attribute() will return null/nothing if there's no such attribute.
In C# I would use:
var idsMissingType = doc.Descendants("ID") // Or whatever
.Where(x => x.Attribute("type") == null);
My guess is that the VB you want is:
Dim ThingList As IEnumerable(Of XElement) = _
From el In doc...<Thing>.<ID> _
Where el.Attribute("type") Is Nothing _
Select el

nullable object must have a value error assigning linq query result to variable

I've created a variable of a class type (CustomerInfo) to store a linq query result and get the error message 'nullable object must have a value' when I view or use the colResults variable, (SurveyDate is a nullable field in the sql table):
Dim var = SurveyDBcontext.QT_Survey_GetSurveySchedule(1, 1, 1).ToList()
Dim colResults = From query In var _
... _
Select New CustomerInfo With { _
.Address = comp.Address, _
.SurveyDate= query.SurveyDate}
If I change the above to:
Dim colResults = From query In var _
... _
Select New With { _
.Address = comp.Address, _
.SurveyDate= query.SurveyDate}
if works fine. Any ideas?
thanks.
Your 'Address' or 'ServeyDate' fields are returning null values and your CustomerInfo class does not allow null values.
The second example is generating an anonymous type which allows nulls. Can you check the actual type that is generated? Guessing SurveyDate is a nullable DateTime in the second example.

.where on a LazyList not working

I am using Rob's implementation of LazyList and it is working great.
However, I am not able to get a .where clause working on a child entity of the type LazyList.
For eg. something like
var qry = orderRepository.GetOrders();
qry = from p in qry where p.Items.Where(t => t.Name == "test") select p;
produces the following compile time error:
Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<Items>' to 'bool'
What is the correct way to query a child entity?
You need Any.
var qry = orderRepository.GetOrders();
qry = from p in qry where p.Items.Any(t => t.Name == "test") select p;
You already have a where clause, and using a second one won't do any good. The first where (the lowercase one) wants a boolean to be able to perform the filtering, but you are providing an IEnumerable<Items> (because that is what the second .Where returns). Any works the same as Where but returns a boolean whenever there's at least one item that matches the query you specified.
Not sure what you are trying to achieve with this statement.
If you want all the orders that have an item with the name "test" then use:
var qry = orderRepository.GetOrders();
qry = from p in qry where p.Items.Any(t => t.Name == "test") select p;
If you want all items that are named "test" then use:
var qry = orderRepository.GetOrders();
qry = from p in qry select p.Items.Where(t => t.Name == "test");

Resources