Option Strict disallows late binding using IEnumerable - asp.net

Dim distinctJoints As IEnumerable
distinctJoints = From row In spotsTable.AsEnumerable()
Group row By Key = row("FUNCJOINTCODE") Into Group
Select Key, Group
_evaluatedJointsCount = (From row In spotsTable.AsEnumerable()
Group row By Key = row("FUNCJOINTCODE") Into Group
Select Key, Group).Count()
'Process each joint
For Each currentJoint In distinctJoints
Dim currentJointKey As String = currentJoint.Key
For the above code currentJoint.Key is showing error of late binding after option strict is on.
Could you please help me out of this.

First, let me congratulate your for moving your code towards Option Strict On! It might be some work in the beginning, but it pays off in the long run since a lot of errors will be found at compile-time rather than at run-time.
That said, let's look at your problem. Here:
Dim distinctJoints As IEnumerable
you declare distinctJoints as a non-generic IEnumerable. A non-generic IEnumerable returns items of type Object when iterated over. The type Object does not contain a Key method. This is why you get a compile-time error.
Since your LINQ query returns a generic IEnumerable of an anonymous type, the solution is to use type inference instead. Activate Option Infer On (if you have not already done so) in your project properties and let the compiler infer the correct data type:
' Dim distinctJoints As IEnumerable <-- remove this
Dim distinctJoints = From row In spotsTable.AsEnumerable()
Group row By Key = row("FUNCJOINTCODE") Into Group
Select Key, Group

Related

How to have a value of NULL for DateTime?

In my SQL database, I've declared DpsDate and AdmDate as DATE, also I've set them to allow nulls. When I run my application and leave these columns blank, I get this error:
Failed to convert parameter value from a String to a DateTime.
This is where I'm a bit confused because I've set them to allow nulls so shouldn't the database accept no value? The application works if I set both dates to "01/01/1900". I've tried setting them to "00/00/0000" but I get the same error.
Here's what I have:
If tbNotifyDate.Text = "" Then
cmd.Parameters.Add("#DpsDate", SqlDbType.Date, 50).Value = "01/01/1900"
Else
cmd.Parameters.Add("#DpsDate", SqlDbType.Date, 50).Value = tbNotifyDate.Text
End If
If tbAdmDate.Text = "" Then
cmd.Parameters.Add("#AdmDate", SqlDbType.Date, 50).Value = "01/01/1900"
Else
cmd.Parameters.Add("#AdmDate", SqlDbType.Date, 50).Value = tbAdmDate.Text
End If
You need to use DBNull.Value to represent NULL in ADO.NET. Things like table adapters and Entity Framework, which are built on top of ADO.NET, can support nullable value types and thus use Nothing to represent NULL but ADO.NET itself predates nullable value types, so Microsoft had to invent a type specifically for the purpose of representing NULL.
I would suggest using the If operator to make the code more concise:
Dim value As Date
cmd.Parameters.Add("#AdmDate", SqlDbType.Date).Value = If(Date.TryParse(tbAdmDate.Text, value),
value,
CObj(DBNull.Value))
The CObj is required because the two possible results of If must be the same type and Date and DBNull are not the same type. By casting one possible result as type Object, they are both interpreted as type Object and the compiler is happy.
Note that, as I have written that example, this will save NULL if the TextBox contains anything that isn't a valid representation of a Date. You can use whatever validation is appropriate in your specific case or, if you've already validated, just check for an empty TextBox and use CDate.

ibm bpm - execute sql statement return type

how to manage the result of a query that returns an integer "select count(*) from table"?
1) I've tried to bind the output of a SQL Execute Statement service to an integer variable and doesn't work. (type mistmatch)
2) i've tried to use types like 'SQLResult', SQLResultRow, SQLResultColumn as well but they dont work:
Caused by: com.lombardisoftware.core.TeamWorksException: Type ismatch the value "[Element: ]" must be and instance of type atructured IBM BPM Java Class found: org.jdom.Element
3) i've tried to bind the output to a XMLElement variable and i've got this value
< resultSet recordCount=\"1\" columnCount=\"1\">5< /columnn>< /record>< /resultSet>
so now... how can I access the recordCount attribute of this node?
anyway, I don't like so manipulate a variable of XMLType, when are the types SQLResult, SQLResultRow, SQLResultColumn used?
****** EDITED *******
even if i get a result as XMLElement.. i can't manipulate it.
methods like: tw.local.result[0].rows[0].column[0].getText() don't work (the intellisense as well)
the XMLElement as an attribute "recordCount" but i don't know how to get his value..
Anyway, the only workaround that i found is to change the query in order to return a normal set of records(not a scalar value)
select field from table instead of select count(field) from table
so i could to map the output value to a list of objects and than count its length...
ugly and dirty :-(
anyone know how manipulate the XMLElement in a script block?
Please try this.
Bind the output variable from sql execute statement as 'ANY' type.
variable name - result (ANY)
Query - select count(field) as COUNTVAL from table
tw.local.totalCount = tw.local.result[0].rows[0].indexedMap.COUNTVAL;
Use Return type as XMLElement then bind a XMLElement in output mapping.
For eg: If you are using tw.local.output as ouput mapping (of type XMLElement) then,
log.info("Count "+tw.local.output.xpath('/resultSet/record/column').item(0).getText());
This will print the count
If you want to get "recordCount" Attribute then use
tw.local.output.getAttribute("recordCount");

nature of SELECT query in MVC and LINQ TO SQL

i am bit confused by the nature and working of query , I tried to access database which contains each name more than once having same EMPid so when i accessed it in my DROP DOWN LIST then same repetition was in there too so i tried to remove repetition by putting DISTINCT in query but that didn't work but later i modified it another way and that worked but WHY THAT WORKED, I DON'T UNDERSTAND ?
QUERY THAT DIDN'T WORK
var names = (from n in DataContext.EmployeeAtds select n).Distinct();
QUERY THAT WORKED of which i don't know how ?
var names = (from n in DataContext.EmployeeAtds select new {n.EmplID, n.EmplName}).Distinct();
why 2nd worked exactly like i wanted (picking each name 1 time)
i'm using mvc 3 and linq to sql and i am newbie.
Both queries are different. I am explaining you both query in SQL that will help you in understanding both queries.
Your first query is:
var names = (from n in DataContext.EmployeeAtds select n).Distinct();
SQL:-
SELECT DISTINCT [t0].[EmplID], [t0].[EmplName], [t0].[Dept]
FROM [EmployeeAtd] AS [t0]
Your second query is:
(from n in EmployeeAtds select new {n.EmplID, n.EmplName}).Distinct()
SQL:-
SELECT DISTINCT [t0].[EmplID], [t0].[EmplName] FROM [EmployeeAtd] AS
[t0]
Now you can see SQL query for both queries. First query is showing that you are implementing Distinct on all columns of table but in second query you are implementing distinct only on required columns so it is giving you desired result.
As per Scott Allen's Explanation
var names = (from n in DataContext.EmployeeAtds select n).Distinct();
The docs for Distinct are clear – the method uses the default equality comparer to test for equality, and the default comparer sees 4 distinct object references. One way to get around this would be to use the overloaded version of Distinct that accepts a custom IEqualityComparer.
var names = (from n in DataContext.EmployeeAtds select new {n.EmplID, n.EmplName}).Distinct();
Turns out the C# compiler overrides Equals and GetHashCode for anonymous types. The implementation of the two overridden methods uses all the public properties on the type to compute an object's hash code and test for equality. If two objects of the same anonymous type have all the same values for their properties – the objects are equal. This is a safe strategy since anonymously typed objects are essentially immutable (all the properties are read-only).
Try this:
var names = DataContext.EmployeeAtds.Select(x => x.EmplName).Distinct().ToList();
Update:
var names = DataContext.EmployeeAtds
.GroupBy(x => x.EmplID)
.Select(g => new { EmplID = g.Key, EmplName = g.FirstOrDefault().EmplName })
.ToList();

EntityFramework using with database foreign key

Actually I spend whole day on the EntityFramework for foreign key.
assume we have two table.
Process(app_id,process_id)
LookupProcessId(process_id, process_description)
you can understand two tables with names, first table ,use process_id to indicate every application, and description is in the seoncd table.
Actually i try many times and figure out how to do inquery: it was like
Dim result = (from x in db.Processes where x.LookupProcess is (from m in db.LookupProcessIds where descr = "example" select m).FirstOrDefault() select x).FirstOrDefault()
First I want to ask is there easier way to do it.
Second i want to ask question is about insert
p As New AmpApplication.CUEngData.Process
p.app_id=100
p.LookupProcess = (from m in db.LookupProcessIds where descr = "example" select m).FirstOrDefault()
db.AddToProcesses(p)
db.SaveChanges()
from appearance it looks fine, but it give me error says
Entities in 'AmpCUEngEntities.Processes' participate in the 'FK_Process_LookupProcess' relationship. 0 related 'LookupProcess' were found. 1 'LookupProcess' is expected.
can i ask is that insert wrong? and is that my query correct?
For your first question:
Dim result = (from x in db.Processes
where x.LookupProcess.descr = "example"
select x).FirstOrDefault()
Actually, you missed some concepts from DataEntityModel, and its Framework. To manipulate data, you have to call object from contextual point of view. Those allow you to specify to the ObjectStateManager the state of an DataObject. In your case, if you have depending data from FK, you will have to add/update any linked data from leaf to root.
This example demonstrate simple (no dependances) data manipulation. A select if existing and an insert or update.
If you want more info about ObjectStateManager manipulation go to http://msdn.microsoft.com/en-us/library/bb156104.aspx
Dim context As New Processing_context 'deseign your context (this one is linked to a DB)
Dim pro = (From r In context.PROCESS
Where r.LOOKUPPROCESS.descr = LookupProcess.descr
Select r).FirstOrDefault()
If pro Is Nothing Then 'add a new one
pro = New context.PROCESS With {.AP_ID = "id", .PROCESS_ID = "p_id"}
context.PROCESS.Attach(pro)
context.ObjectStateManager.ChangeObjectState(pro, System.Data.EntityState.Added)
Else
'update data attibutes
pro.AP_ID = "id"
pro.PROCESS_ID = "p_id"
context.ObjectStateManager.ChangeObjectState(pro, System.Data.EntityState.Modified)
'context.PROCESS.Attach(pro)
End If
context.SaveChanges()
I hope this will help. Have a nice day!
For your first question, to expand on what #jeroenh suggested:
Dim result = (from x in db.Processes.Include("LookupProcess")
where x.LookupProcess.descr = "example"
select x).FirstOrDefault()
The addition of the Include statement will hydrate the LookupProcess entities so that you can query them. Without the Include, x.LookupProcess will be null which would likely explain why you got the error you did.
If using the literal string as an argument to Include is not ideal, see Returning from a DbSet 3 tables without the error "cannot be inferred from the query" for an example of doing this using nested entities.
For your second question, this line
p.LookupProcess = (from m in db.LookupProcessIds
where descr = "example" select m).FirstOrDefault()
Could cause you problems later on because if there is no LookupProcessId with a process_description of "example", you are going to get null. From MSDN:
The default value for reference and nullable types is null.
Because of this, if p.LookupProcess is null when you insert the entity, you will get the exception:
Entities in 'AmpCUEngEntities.Processes' participate in the 'FK_Process_LookupProcess' relationship. 0 related 'LookupProcess' were found. 1 'LookupProcess' is expected.
To avoid this kind of problem, you will need to check that p.LookupProcess is not null before it goes in the database.
If Not p.LookupProcess Is Nothing Then
db.AddToProcesses(p)
db.SaveChanges()
End If

Failed to convert parameter value from a TimeSpan to a DateTime

I am trying to store a time from my textbox field value but I got this exception error, what am I doing wrong? Thanks!:
Failed to convert parameter value from a TimeSpan to a DateTime.
Passing textbox value:
.CamActiveDateFrom = CDate(uitxtCamDateStart.Text.Trim)
My variable and property:
Private _camActiveTimeFrom As Nullable(Of TimeSpan)
Public Property CamActiveTimeFrom() As Nullable(Of TimeSpan)
Get
Return Me._camActiveTimeFrom
End Get
Set(ByVal value As Nullable(Of TimeSpan))
Me._camActiveTimeFrom = value
End Set
End Property
Parameter:
AddInParameter(dbCommand,
"#ActiveTimeFrom", DbType.Time, 6, DBNull.Value)
If (.CamActiveTimeFrom).HasValue Then
dbCommand.Parameters("#ActiveTimeFrom").Value = .CamActiveTimeFrom
End If
DbType.Time is documented as:
A type representing a SQL Server DateTime value. If you want to use a SQL Server time value, use SqlDbType.Time.
So either use SqlDbType.Time instead, or set the value to a DateTime value instead of a TimeSpan value.
Admittedly this mapping table show the DbType.Time mapping to TimeSpan, so there's some inconsistency here - but if you can use a more specific type, that can only be good.
Of course it's easy to construct a DateTime from a TimeSpan if you want to - you should probably decide on a specific date to always use (e.g. 1st January 2000) so that you can then compare values within the database and effectively get a comparison of just the time bits.
I hav the same problem. And I soloved it just used "ToString()".
my code as following:
the date type of "info.START_TIME" is TimeSpan.
db.AddInParameter(dbCommand, "#START_TIME", DbType.Time, info.START_TIME.ToString());
In order to use AddInParameter with a column of data type time, you need to use the SqlDbType instead of DbType (as described in Jon Skeet's answer)
db.AddInParameter(dbCommand, "#ActiveTimeFrom", SqlDbType.Time, 6, DBNull.Value)
instead of
db.AddInParameter(dbCommand, "#ActiveTimeFrom", DbType.Time, 6, DBNull.Value)
BUT.
In order you use SqlDbType.Time instead of DbType.Time, you must declare your Database object as an SqlDatabase, that is
SqlDatabase db = (SqlDatabase)DatabaseFactory.CreateDatabase();
instead of
Database db = DatabaseFactory.CreateDatabase();
as otherwise it won't take the parameter.

Resources