I need the following LINQ statement corverted to VB.net. but
collection.Select(c => {c.PropertyToSet = value; return c;});
Here's what I have, but I want to do the 'return' instruction.
collection.Select(function (c) c.PropertyToSet = value ***return c*** )
Any ideas on how to get that converted?
Thanks a lot!
If you want to change all properties of an object in the collection, Select method is not appropriated method to do this.
Since the collection object is a List(Of T), you could try this with ForEach method:
collection.ForEach(Sub(c) c.PropertyToSet = value)
With Select method, you could try this:
collection = collection.Select(Sub(c) c.PropertyToSet = value)
Alternatively, you could use the language structure For Each for it:
For Each c as YourType In collection
c.PropertyToSet = value
Next
I think this is the way, did not test it but it should work
Collection.Select(Function(c)
c.PropertyToSet = value
Return c
End Function)
If you are looking to get a filtered IList back, try this:
collection.Where(Function(c) c.PropertyToSet = Value).ToList
Related
I have a list of it, that is my SelectedValue from some ComboBox.
Dim AppsInt = MyApps.CheckedItems.Select(Function(x) Convert.ToInt32(x.Value)).ToList()
And i have this object that is a list( of t)
Dim myObj = New List( Of Item )
Dim FooItem = New item ( 42 )
What I want is to get my list of Int into my object. With Something that would look like this in C#:
AppsInt.foreach( x => myObj .add(new Item(x) ) ) ;
What i have done so far is sending me a "do not produce a result" error:
AppsInt.ForEach( Function(it) myObj.Add(New Item(it)) )
How can i do it ? How to make this linq lambda work?
you should change function(it) to sub(it) .
Or:
Dim myObj = AppsInt.Select( Function(it) New Item(it)).ToArray()
Lambda expression inside you ForEach expression does not returns any result (and compiler said it to you). It means that you have two ways to solve it:
Add return statement into your lamda expression that will return anything:
AppsInt.ForEach(Function(it)
myObj.Add(New Item(it))
Return 1 ' it's not matter what you will return here.
End Function)
Change Function(it) to Sub(it). Sub is not obliged to return any value.
Second option is more preferable.
A property from my object (oJobs) is as follows:
Private _brandlist As List(Of DAL.Brand)
Public Property PostBrandList() As List(Of DAL.Brand)
Get
Return _brandlist
End Get
Set(ByVal value As List(Of DAL.Brand))
_brandlist = value
End Set
End Property
In the database, the brand list is stored as a string separated by comma e.g. the column 'brands' can be a string '3,45,2' where each number represents an id of a brand stored in another table.
my select query is as below:
Dim jobposts As List(Of oJobs) = From j In db.JobPostings
Select New oJobs With { 'hiding all others for code brevity
.PostBrandList = 'problem is here'
}
Since j.BrandList will return a string, I will need to split that string and for each number, run another query to finally return and assign a List(Of DAL.Brand) into .PostBrandList
For those who might ask "what have you tried?",
I have run the query, then did a for each to add the list of brands later - succeeded but not optimal
Coded a function that takes the list as a parameter and returns a separate list of objects - very silly.
Also, I am not allowed to normalize the DB :(
Not tested and might need some tweaking but heres one idea. you will also need to change your property to an IEnumerable rather than List. Because the second linq query is embedded within the first, I believe it should execute it all as one query, but you should check it to make sure.
Dim jobposts As List(Of oJobs) = From j In db.JobPostings
Select New oJobs With { 'hiding all others for code brevity
.PostBrandList = From b In db.Brands Where j.Brands = b.ID Or j.Brands.StartsWith(b.ID & ",") Or j.Brands.EndsWith("," & b.ID) Or j.Brands.Contains("," & b.ID & ",") Select b
}
In c# you can use
.Select(x=>new {x.BrandList})
.ToList() //Materialize first before calling function
.Select(x=> new oJobs{
PostBrandList =
db.Brands.Where(z=>
x.BrandList
.Split(',')
.Select(y=>int.Parse(y.Trim()))
.Contains(z.Id))
.ToList()
});
Note that you must materialize entity first before calling String.Split
I don't know how to translate that to VB.NET.
Of course it will cause SELECT n+1 problem because you can't use join.
If you can't normalize table, my other suggestion is to create indexed view (sql server), so you can use join and improve performance.
Indexed view https://msdn.microsoft.com/en-us/library/ms191432.aspx
You could try it with the Let statement:
Dim jobposts As List(Of oJobs) = From j In db.JobPostings
/* li in the LINQ Statement represents one string value from the BrandList list */
Let postBrandElemsList = j.BrandList.Split(',').Select(Function(li) New DAL.Brand With { ... /* Field initializatione of the Class DAL.Brand here */ }
Select New oJobs With
{
.PostBrandList = postBrandElemsList
}
I'm sorry for the probably bad VB.NET syntax, you should check this when implementing it in your code.
Maybe you would just want to use the Split function on the column brands into an array and iterate through the result, using the Find function to retrieve the brand objects?
Dim obj As New CMS_Page
Dim comparisonObj As New CMS_Page
The assignment
obj = db.CMS_Pages.First(Function(s) s.PageID = pageID)
comparisonObj = db.CMS_Pages.First(Function(s) s.PageID = pageID)
Somwhere in the middle of my code
obj.property = sometextfield.text 'Apparently this also changes the comparisonObj
Basically what I'm doing in the end would be
if (obj.property = comparisonObj.property) then
//...
end if
Why can't i change obj.Property without it changing the same property in comparisonObj.Property?
You are probably setting "comparisonObj = obj". You probably want "comparisonObj = obj.Clone()". You will have to implement the "Clone" method yourself.
If CMS_Page is not under your control, then you can create an extension method to clone it.
obj = db.CMS_Pages.First(Function(s) s.PageID = pageID)
comparisonObj = db.CMS_Pages.First(Function(s) s.PageID = pageID)
These two lines result in two references to the same object. Hence, when you do this: obj.property = sometextfield.text then comparisonObj will also reflect that change.
What is the result of
obj.ReferenceEquals(comparisonObj)
if that is True then obj is comparisonObj. You can do the same check more concisely like this,
obj Is comparisonObj
If you have a VB background, both variables are references to the same object.
If you have a C background, both variables are pointers to the same object.
essentially, the variable holds an integer value that addresses the object in memory.
I need to build an array of objects of class ID using arrayfun:
% ID.m
classdef ID < handle
properties
id
end
methods
function obj = ID(id)
obj.id = id;
end
end
end
But get an error:
>> ids = 1:5;
>> s = arrayfun(#(id) ID(id), ids)
??? Error using ==> arrayfun
ID output type is not currently implemented.
I can build it alternatively in a loop:
s = [];
for k = 1 : length(ids)
s = cat(1, s, ID(ids(k)));
end
but what is wrong with this usage of arrayfun?
Edit (clarification of the question): The question is not how to workaround the problem (there are several solutions), but why the simple syntax s = arrayfun(#(id) ID(id), ids); doesn't work. Thanks.
Perhaps the easiest is to use cellfun, or force arrayfun to return a cell array by setting the 'UniformOutput' option. Then you can convert this cell array to an array of obects (same as using cat above).
s = arrayfun(#(x) ID(x), ids, 'UniformOutput', false);
s = [s{:}];
You are asking arrayfun to do something it isn't built to do.
The output from arrayfun must be:
scalar values (numeric, logical, character, or structure) or cell
arrays.
Objects don't count as any of the scalar types, which is why the "workarounds" all involve using a cell array as the output. One thing to try is using cell2mat to convert the output to your desired form; it can be done in one line. (I haven't tested it though.)
s = cell2mat(arrayfun(#(id) ID(id), ids,'UniformOutput',false));
This is how I would create an array of objects:
s = ID.empty(0,5);
for i=5:-1:1
s(i) = ID(i);
end
It is always a good idea to provide a "default constructor" with no arguments, or at least use default values:
classdef ID < handle
properties
id
end
methods
function obj = ID(id)
if nargin<1, id = 0; end
obj.id = id;
end
end
end
My Sql Query in Vb.net is like this:
Dim TableName As String ="City"
Dim Str As String="Select * from "+TableName+""
I got TableName from another Form .how we can do this in linq?
can we use TableName in Linq query dynamically?
please help me?
Sorry for my example being in C#, but my Vb is rusty. I can read it, but not write it very well off the top of my head.
The best way I can think to do this is to use reflection and extension methods rather than LINQ syntax.
PropertyInfo info = dataContext.GetType().GetProperty( "City" );
IQueryable table = info.GetValue( dataContext, null ) as IQueryable;
var query = table.Where( t => t.Column == "Value" )
.Select( t => t.OtherColumn );
I'm assuming LINQtoSQL in this example and so am getting the object from the datacontext. If you're using something else, you'll need to adjust the method of finding the object.
You could also use a stack of if-then statements based on the value of the table name. If the number of possible tables was fixed and small, this might be better.
i got the idea, thanks, very helpful, however i couldnt be able to see those properties.
string linqObjectName = "Test";
PropertyInfo info = db.GetType().GetProperty(linqObjectName);
IQueryable table = info.GetValue(db, null) as IQueryable;
PropertyInfo[] properties = table.GetType().GetProperties();
ltr.Text += "properties: <hr size=1/>";
foreach (PropertyInfo p in properties)
{
ltr.Text += p.Name + "<br />";
}
and thats the result;
properties:
Context
IsReadOnly
Edit: I found it!
PropertyInfo[] properties =
table.Where("WebRef = \"" + webref + "\"").ElementType.GetProperties();