How to split a MULTIPLE integers values column in linq - asp.net

I have to filter the records based on a column(datatype: string) integers values using LINQ for eg., IDs: 3,34,35,36,98,43.
Also i tried with the split in linq, this is my scenario
Banners = Banners.Where(Function(x) Not String.IsNullOrEmpty(x.IDs) AndAlso x.[IDs].Split(New Char() {","c}, StringSplitOptions.RemoveEmptyEntries).Select(Function(a) Convert.ToInt32(a)).Contains(3))
my Scenario when doing the split on the IDs it shows a error
Failure: Execution of 'System.Linq.Enumerable:Contains(IEnumerable`1,Int32)' on the database server side currently not implemented.
How to filter the record based on the column IDs integer value using linq?

Replace the .Contains with .Where(x=>x==3).FirstOrDefault() and check for non null.
Personally if that is your data structure I would consider redesigning the db. If that doesn't happen, don't bother with converting to int. Just search for strings.

You can't use Split in LINQ to SQL but you can use String.Contains so translate the Split/Contains into String.Contains:
Banners = Banners.Where(Function(x) Not String.IsNullOrEmpty(x.IDs) AndAlso (","+x.[IDs]+",").Contains(","+"3"+","))

I was not sure about your Banner Class
but I tried with below logic, and it just worked fine
Module Module1
Sub Main()
Dim Banners = New List(Of Banner)
Banners = Banners.Where(Function(x) Not String.IsNullOrEmpty(x.IDs) AndAlso x.[IDs].Split(",").Select(Function(a) Convert.ToInt32(a)).Contains(3)).ToList()
End Sub
End Module
Class Banner
Private _IDs As String
Public Property IDs() As String
Get
Return "3,34,35,36,98,43"
End Get
Set(ByVal value As String)
_IDs = value
End Set
End Property
End Class
Only Change I have is I have added ToList() at the end of Statement while assigning to Banners object

Related

How do I write a VB.Net method to filter a URLs?

I am attempting to write a method using VB.NET that will allow me to read in a URL and compare it to a list. If it is one of the URLs on the list then Bing Tracking conversion will be applied.
At the moment I can only think do write it as a comaparative method, comapring the current URL with the ones that require tracking (a list). This, however, sems a little long winded.
Each page may have a different querystring value/page id, there for its fundamental to get exactly the right page for the tracking to be applied to.
Any Ideas?
Sorry I really am a novice when developing functions in VB.Net
If I were to use th Contains() function then I would imagine that it would look a little something like this:
Private sub URL_filter (ByVal thisPage As ContentPage, brandMessage? As Boolean) As String
Dim url_1 As String = "/future-contact thanks.aspx"
Dim url_2 As String = "/find-enquiry thanks.aspx?did=38"
Dim url_3 As String = "/find-enquiry-thanks.aspx?did=90"
Dim url_4 As String = "/find-enquiry-thanks.aspx?did=62"
Dim result as String
result = CStr (url_1.Contains(current_URL))
txtResult.Text = result
End Sub
If I were to use this then what type of loop would I have to run to check all the URLs that are in my list against the current_URL? Also where would I define the current_URL?
You can use the Contains() function to check if the list contains the given value. You could also implement a binary search, but it is probably overkill for your purposes. Here is an example:
Dim UrlList As New List(Of String)
UrlList.Add("www.example2.net") 'Just showing adding urls to the list
UrlList.Add("www.example3.co.uk")
UrlList.Add("www.exampletest.com")
Dim UrlToCheck As String = "www.exampletest.com" 'This is just an example url to check
Dim result As Boolean = UrlList.Contains(UrlToCheck) 'The result of whether it was found
Make sure to add these imports Imports System and Imports System.Collections.Generic
Disclaimer: I have no experience with VB.NET

Inserting null values into date fields?

I have a FormView where I pull data from one table (MS Access), and then insert it (plus more data) into another table. I'm having issues with the dates.
The first table has two date fields: date_submitted and date_updated. In some records, date_updated is blank. This causes me to get a data mismatch error when attempting to insert into the second table.
It might be because I'm databinding the date_updated field from the first table into a HiddenField on the FormView. It then takes the value from the HiddenField and attempts to insert it into the second table:
Dim hfDateRequestUpdated As HiddenField = FormView1.FindControl("hfDateRequestUpdated")
myDateRequestUpdated = hfDateRequestUpdated.Value
'... It then attempts to insert myDateRequestUpdated into the database.
It works when there is a value there, but apparently you can't insert nothing into a date/time field in Access. I suppose I could make a second insert statement that does not insert into date_updated (to use when there is no value indate_updated), but is that the only way to do it? Seems like there should be an easier/less redundant way.
EDIT:
Okay. So I've tried inserting SqlDateTime.Null, Nothing, and DBNull.Value. SqlDateTime.Null results in the value 1/1/1900 being inserted into the database. "Nothing" causes it to insert 1/1/2001. And if I try to use DBNull.Value, it tells me that it cannot be converted to a string, so maybe I didn't do something quite right there. At any rate, I was hoping that if there was nothing to insert that the field in Access would remain blank, but it seems that it has to fill it with something...
EDIT:
I got DBNull.Value to work, and it does insert a completely blank value. So this is my final working code:
Dim hfDateRequestUpdated As HiddenField = FormView1.FindControl("hfDateRequestUpdated")
Dim myDateRequestUpdated = Nothing
If hfDateRequestUpdated.Value = Nothing Then
myDateRequestUpdated = DBNull.Value
Else
myDateRequestUpdated = DateTime.Parse(hfDateRequestUpdated.Value)
End If
Thanks everyone!
Sara, have you tried casting the date/time before you update it? The data mismatch error likely comes from the fact that the hfDateRequestUpdated.Value you're trying to insert into the database doesn't match the column type.
Try stepping through your code and seeing what the type of that value is. If you find that it's a string (which it seems it might be, since it's coming from a field on a form), then you will need a check first to see if that field is the empty string (VBNullString). If so, you will want to change the value you're inserting into the database to DBNull, which you can get in VB.Net using DBNull.Value.
We can't see your code, so we don't know exactly how you get the value into the database, but it would look something like this
If theDateValueBeingInserted is Nothing Then
theDateValueBeingInserted = DBNull.Value
EndIf
Keep in mind that the above test only works if the value you get from the HiddenField is a string, which I believe it is according to the documentation. That's probably where all this trouble you're having is coming from. You're implicitly converting your date/time values to a string (which is easy), but implicitly converting them back isn't so easy, especially if the initial value was a DBNull
aside
I think what Marshall was trying to suggest was the equivalent of the above code, but in a shortcut expression called the 'ternary operator', which looks like this in VB.Net:
newValue = IF(oldValue is Nothing ? DBNull.Value : oldValue)
I wouldn't recommend it though, since it's confusing to new programmers, and the syntax changed in 2008 from IFF(condition ? trueResult : falseResult)
Your code
Dim myDateRequestUpdated As DateTime
myDateRequestUpdated = DateTime.Parse(hfDateRequestUpdated.Value) : DBNull.Value()
has a couple of problems:
When you declare myDateRequestUpdated to be DateTime, you can't put a DbNull.Value in it.
I'm not sure you need the () for DbNull.Value: it's a property, not a method (I don't know enough VB to say for sure)
VB doesn't know that : operator
What you probably want is a Nullable(Of DateTime) to store a DateTime value that can also be missing.
Then use something like this to store the value:
myDateRequestUpdated = If(String.IsNullOrWhiteSpace(hfDateRequestUpdated.Value),
Nothing, DateTime.Parse(hfDateRequestUpdated.Value))
If hfDateRequestUpdated.Value is empty, then use Nothing as the result; else parse the value as date (which might fail if it is not a valid date!).
Try this:
Protected Sub Button2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim str As String
If TextBox1.Text.Length <> 0 Then
str = "'" & TextBox1.Text & "'"
Else
str = "NULL"
End If
sql = "insert into test(test1) values(" & str & ")"
dsave_sql(sql)
End Sub
Function save_sql(ByVal strsql As String, Optional ByVal msg As String = "Record Saved Sucessfully") As String
Dim sqlcon As New SqlConnection(strConn)
Dim comm As New SqlCommand(strsql, sqlcon)
Dim i As Integer
Try
sqlcon.Open()
i = CType(comm.ExecuteScalar(), Integer)
save_sql = msg
Catch ex As Exception
save_sql = ex.Message
End Try
sqlcon.Close()
Return i
End Function

Using arrays with asp.net and VB

Sorry, I'm sure this is something that has been covered many times, but I can't find quite what I am after.
I have a single row data table which contains various settings which are used within my web system. I have been toying with turning this into an XML document instead of the single row datatable, would that make more sense?
Anyway, so, given that this is one record, there is a field called "locations," this field contains data as follows:
locationName1,IpAddress|locationName2,IpAddress|etc
The ipAddress is just the first 5 digits of the IP and allows me to ensure that logins to certain elements (admin section managed by staff) can only be accepted when connected from a company computer (ie using our ISP) - this is a largely unnecessary feature, but stops kids I employ logging in at home and stuff!
So, as the user logs in, I can check if the IP is valid by a simple SQL query.
SELECT ips FROM settings WHERE loginLocations LIKE '%" & Left(ipAddress, 5) & " %'
What I need to be able to do now, is get the name of the users location from the dataField array.
I've come up with a few long winded looping procedures, but is there a simple way to analyse
locationName1,IpAddress1|locationName2,IpAddress2|etc
as a string and simply get the locationName where LoginIp = IpAddressX
... or am I going about this in a totally ridiculous way and should turn it into an xml file? (which will then create a whole load of other questions for you about parsing XML!!)
u can split the string in Vb.net and the send it to a query or anything
'Split the string on the "," character
Dim parts As String() = s.Split(New Char() {","c})
In SQL Server, these are the functions of interest in extracting a sub-string:
CHARINDEX
SUBSTRING
LENGTH
You can google the details about them (e.g. CHARINDEX at http://msdn.microsoft.com/en-us/library/ms186323.aspx). With these, you'll need to use computed columns in your query to extract that location name.
If it's not too late, you may want to devise a new way to layout these elements. For instance, instead of:
locationName1,IpAddress1|locationName2,IpAddress2|etc
How about
{IpAddress1,locationName1}{IpAddress2,locationName2}etc
That way you can use CHARINDEX to locate "{" & Left(ipAddress, 5); from that position, locate ","; then from that position locate the closing "}". From there it should be straightforward to use SUBSTRING to get at the locationName. Be forewarned that this will likely be a messy query (probably built from a few sub-queries, one for each position).
In the end, SpectralGhost's idea to just read in the column and do the extraction in VB is probably the way with the least hassle.
I've decided to do it this way, but would appreciate comments on efficiency.
I've split ipAddress and locationName into two database columns, within the one row, and getting the required data by comparing strings as arrays, as per the code below.
For this particular application I'm only dealing with one record, so it's pretty simple. However, further down the line, I need to product a system for monitoring product sales. from an invoices table.
Each invoice record is a row in the database with items in the invoice held similarly, [item1],[item2] etc. There is another column for quantities [qty1],[qty2] etc, prices [price1],[price2], etc. I'll need to be able to search the database for invoices in which an item number occurs (easy SQL WHERE itemList LIKE %[invNO]%) and then compare arrays to get the quantities and individual prices of each item on that invoice. Extracting these rows as arrays and locating the relevant position in these as per the code below, will work fine, but when the whole operation is looping through several hundred or thousand rows, will this become really slow?
ipList, locationList = list as comma separated string from database record field
Dim ipArray As Array = Split(ipList, ",")
Dim locationArray As Array = Split(locationList, ",")
For i = 0 To UBound(ipArray)
If Left(ipArray(i), 5) = Left(ipAddress, 5) Then
arrayPosition = i
itemFound = "True"
Exit For
End If
Next
location = locationArray(arrayPosition)
'loop through ips then get the position and make the location equal to that
If itemFound <> "True" Then
inValidIP = "True"
End If
I strongly advise that you break those our into database columns and each location is a separate row; had it been done that way in the first place, you wouldn't have the problem you have now.
But since you have it in a single row/column, why not bring that back and simply get the value from .NET?
Dim Source As String = "TestLocationA,127.0|TestLocationB,128.0|TestLocationC,129.0"
Dim Test As String = Source
Dim ToFind As String = "127.0"
Test = Test.Substring(0, Test.IndexOf(ToFind & "|") - 1)
Test = Test.Substring(Test.LastIndexOf("|") + 1)
MsgBox(Test)
OR
Public Class Form1
Private IpLocationList As New List(Of IpLocation)
Private IpToFind As String = ""
Private Class IpLocation
Public Name As String
Public IP As String
Public Sub New(ByVal FullLocation As String)
Me.Name = FullLocation.Substring(0, FullLocation.IndexOf(","))
Me.IP = FullLocation.Substring(FullLocation.IndexOf(",") + 1)
End Sub
End Class
Private Function FindIP(ByVal IpLocationItem As IpLocation) As Boolean
If IpLocationItem.IP = IpToFind Then
Return True
Else
Return False
End If
End Function
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim Source As String = "TestLocationA,127.0|TestLocationB,128.0|TestLocationC,129.0"
Dim LocationList As New List(Of String)
LocationList.AddRange(Split(Source, "|"))
For Each LocationItem As String In LocationList
IpLocationList.Add(New IpLocation(LocationItem))
Next
IpToFind = "127.0"
Dim result As IpLocation = IpLocationList.Find(AddressOf FindIP)
If result IsNot Nothing Then
MsgBox(result.Name)
End If
End Sub
End Class
enter code here
This has the benefit of loading the array one time and not needing to manually loop through arrays.

Do I Need a Class if I only need 1 Property (at the moment)?

Update: I didn't make it clear but I meant this to be a question about where/how I would use a function to return a list of strings when I'm trying to just work with classes.
I have a class called Account.
I have data access class called AccountDAO.
I have various functions that return lists of objects like GetAllAccounts, GetAccountByID etc.
I want to populate a drop down list with just the account names and nothing else. It's proving rather slow when using lists of objects and databinding them to the dropdownlist.
I feel like I should be using a simple "Select Account_Name From blah" type statement and returning a list of strings but I don't know how to work this into my class and data access class.
How should I handle this predicament?
You can use a list of string,s and bind the list of strings to a dropdownlist no problem... the DDL can support that, just leave out DataTextField and DataValueField props, and it will display the account name as is, which that name would be accessible through the ListItem's Text and Value property.
I like to use objects to be consistent with the rest of the app (which other areas might need a class), and if for some reason you want to add AccountKey later, if you use an object, all you need to do is add a property. Otherwise, if using strings, you'd have to switch up the binding later to point to the object.
HTH.
There is nothing wrong by making a function that only returns a list of strings. YOu could however wonder if it's not better to restrict the number of records you want to put in the list and use some kind of paging.
Assuming that you're using a List<>, you can try something like this:
IEnumerable<string> nameList = accountList.Select(t => t.AccountName);
Or if you need a List:
List<string> nameList = accountList.Select(t => t.AccountName).ToList();
Go with your feelings. Use a datareader to select the list and then load them into an arraylist which can then be bound to the dropdown. Alternately, use something like this method I use to provide both a DisplayMember and a ValueMember which uses a class (with both values) as members of the arraylist. This should give you the general idea. (Note: I normally include this code in a data access class (MyBase) where StartReader, _datRdr, ReadNext and_ReaderValid are a members. But the general idea is intact.)
Public Sub LoadDataSource(ByRef PlantDataSource As PlantSource, Optional ByVal Filter As String = "", Optional ByVal IncludeBlankItem As Boolean = False)
PlantDataSource = New PlantSource
If IncludeBlankItem Then
PlantDataSource.Add(0, "")
End If
If Filter = String.Empty Then
Call StartReader(" Order by PlantName")
Else
Call StartReader(String.Concat(" Where ", Filter, " Order by PlantName"))
End If
If _DatRdr.HasRows Then
While MyBase._ReaderValid
PlantDataSource.Add(PlantId, PlantName)
ReadNext()
End While
End If
Call CloseReader()
End Sub
Private Class PlantListing
Private _PlantList As New ArrayList
Public Sub Add(ByVal PlantId As Integer, ByVal PlantName As String)
_PlantList.Add(New PlantDataItem(PlantId, PlantName))
End Sub
Public ReadOnly Property List() As ArrayList
Get
Return _PlantList
End Get
End Property
End Class
Private Class PlantDataItem
Private _PlantId As Integer
Private _PlantName As String
Public Sub New(ByVal pPlantId As Integer, ByVal pPlantName As String)
Me._PlantId = pPlantId
Me._PlantName = pPlantName
End Sub
Public ReadOnly Property PlantName() As String
Get
Return _PlantName
End Get
End Property
Public ReadOnly Property PlantId() As Integer
Get
Return _PlantId
End Get
End Property
Public ReadOnly Property DisplayValue() As String
Get
Return CStr(Me._PlantId).Trim & " - " & _PlantName.Trim
End Get
End Property
Public Overrides Function ToString() As String
Return CStr(Me._PlantId).Trim & " - " & _PlantName.Trim
End Function
End Class

Auto generate grid using mvccontrib by passing datatable in ASP.net MVC 2 application

In My project i want to use the mvccontrib (http://mvccontrib.codeplex.com) to auto generate grid by passing the DataTable to the Grid. Currently Grid does not support this.
Grid takes IEnumerable(Of T) and auto generate columns. Is their any way i can achieve this by passing DataTable. Or How do i convert the DataTable to IEnumerable(Of T). My DataTable is completely Dynamic i don't know number of columns or names of the columns at design time. DataTable completely dynamic number of columns are not fixed it just any DataTable.
How can i achieve this?
In Short i want to convert Dynamic DataTable to IEnumerable(Of T). Or Is their any better way.
I tried following way
1) One way i tried is using .net 4.0 Dynamic, DynamicObject and ExpandoObject
I created a dynamic class as shown here http://msdn.microsoft.com/en-us/library/system.dynamic.dynamicobject.trygetindex.aspx. I trid passing IEnumerable(Of SampleDynamicObject) but BuildColumns() method is not able to find out the proprieties dynamically added on to it.
2) I think Second way to modify the AutoGenerateColumns() method to work with DataTable, But it looks impossible as Grid Get initialize using IEnumerable(Of T) and all the call on grid for method is using IEnumerable(Of T). So it's come down to converting DataTable to IEnumerable(Of T) and my DataTable are dynamic i don't know their structure at design time So i can't write any specific class to create a object and convert DataTable to IEnumerable(Of T).
Does any one have any better way out on this.
Thanks
Sandy
The question is quite old but maybe this could help someone else. I just needed to fill grid with dynamic DataTable and I do it like this in view:
Index.cshtml
#using System.Data
#using MvcContrib.UI.Grid
#model SomeDataTable
#Html.Grid(Model.Rows.Cast<DataRow>()).Columns(columns =>{
foreach (var dataColumn in Model.Columns.Cast<DataColumn>()){
var column = dataColumn;
columns.For(x => x[column]).Named(column.Caption);
}
})
If you're using .NET 3.5, you can use AsEnumerable (from DataTableExtensions. It would look something like this:
IEnumerable<DataRow> data = datatable.AsEnumerable();
It is possible by creating a custom GridModel.
Here I based my grid on an IList filled with IDictionaries, but this should also be possible with data taken from a DataTable.
The trick is to give the data structure to the constructor of the custom GridModel and let the custom GridModel generate columns based on the data structure.
It is a bit ugly, but it works good.
(and it is even uglier in VB.NET with the funny lambda expressions)
The controller action code:
Dim list As IList(Of IDictionary(Of String, String)) = New List(Of IDictionary(Of String, String))
Dim row1 As IDictionary(Of String, String) = New Dictionary(Of String, String)()
row1.Add("Column1", "ValueColumn1Row1")
row1.Add("Column2", "ValueColumn2Row1")
Dim row2 As IDictionary(Of String, String) = New Dictionary(Of String, String)()
row2.Add("Column1", "ValueColumn1Row2")
row2.Add("Column2", "ValueColumn2Row2")
list.Add(row1)
list.Add(row2)
ViewData("DynamicData") = list
The custom GridModel:
Public Class DynamicGridModel
Inherits MvcContrib.UI.Grid.GridModel(Of IDictionary(Of String, String))
Public Sub New(ByVal dataToRender As IList(Of IDictionary(Of String, String)))
If dataToRender.Count > 0 Then
For Each name As String In dataToRender(0).Keys
Dim columnName As String = name
Column.For(Function(rowData As IDictionary(Of String, String)) rowData(columnName)).Named(columnName)
Next
End If
End Sub
End Class
The syntax in the view:
Html.Grid(Of IDictionary(Of String, String))("DynamicData").WithModel(New DynamicGridModel(ViewData("DynamicData")))

Resources