WHERE IN query in linq - c#

public Class SomeModel
{
public int Id { get; set;}
public string Name {get; set;}
}
this is the method I'm binding values to above model, it contains inline SQL Queries
Public ActionResult GetData()
{
IEnumarable<SomeModel> alltheListValues = ....
}
using above method, I want to filter all the record that containing ids in following string.
string filterIds = "12,13,14,15"
SomeModel model class Id values are in Integer type, but I have string type id set, without going for looping this, I decided to use WHERE IN query to filter this.
since WHERE IN query we can get in Linq as contains
I wrote down follwoing function to filter values
IEnumarable<SomeModel> filterValues = GetData.Where(Id=> Id.ToString().Contains(filterIds));
but this is not selecting any value always zero filter result, how can I wrote this properly

This could be a way to go:
string filterIds = "12,13,14,15";
//Convert filterIds string into a integers collection
var ids=filterIds.Split(',').Select(int.Parse);
IEnumarable<SomeModel> filterValues = GetData().Where(sm=> ids.Contains(sm.Id));
One thing I noticed now is the signature of your GetData method, I think what you mean is:
public IEnumarable<SomeModel> GetData()
{
IEnumarable<SomeModel> alltheListValues = ....
//...
return alltheListValues;
}

Have a array/collection instead of a list and check if the id is in it.
IEnumarable<SomeModel> filterValues = ActualGetData().Where(n => filterIds.Contains(n.Id))
Where ActualGetData() returns you an IEnumarable.
In your current code GetData() returns an ActionResult as Drew Kennedy mentioned

If you are sure that all the elements of collection of "Id" will be convertible to number then you can use following approach.
var models = new List<SomeModel>(); //Consider that this collection is coming from some service or repository.
var Ids = filterIds.Split(',').Select(x => int.Parse(x));
IEnumarable<SomeModel> filterValues = models.Where(n => Ids.Contains(n.Id));
Your code wound't compile so I am posting here just the logical code here. You can use it as per your requirement.

Related

Cannot display the list of names into the view

I have a list that I prepare in a ViewModel to take values from database table. The list assigned into a model class:
public class DType
{
public string DTName { get; set; }
}
And it get updated by the following method:
public static List<DType> GetDocTypesString(Entity DB, int RKey)
{
return DB.Database.SqlQuery<DType>(#"SELECT * FROM Names
WHERE NK = {0}", RKey).ToList();
}
And then I return the list (model) to the view to list the names into a select menu as the following:
The actual returned model to the view:
public List<DType> ihName { get; set; }
it gets populated by using the method above:
ihName = GetDocTypesString(DB, RKey);
And then, in the view, I use the below:
#Html.Partial("GettingNamesPartial", new ProjName.ViewModels.UploadingPartialViewModel
{
DropdownIHDocType = new SelectList(Model.ihEditorInstanceName)
})
The results are always like this:
Instead to displaying the actual names, the list (select) display:
ProjName.ViewModels.DType
ProjName.ViewModels.DType
ProjName.ViewModels.DType
ProjName.ViewModels.DType
The only thing that matches is the number of items is the same as the names on the database table.
Important Note:
Before trying to pull the names from the database, the list worked just fine by hard coding the names like the following:
DropdownIHDocType = new SelectList(new string[] { "Morgan", "Sam", "Shawn" })
ihName = GetDocTypesString(DB, RKey);
is your culprit. your getting a list of document types, not the variable name from each of those documents. basically your showing the class not its content. you need to get access to the actual document, then find the variable you need and assign that to ihName
so you're grabbing DType not DType.DTname which is what i assume your trying to list

MongoDB Linq OfType() on fields

This is my MongoDB document structure:
{
string _id;
ObservableCollection<DataElement> PartData;
ObservableCollection<DataElement> SensorData;
...
other ObservableCollection<DataElement> fields
...
other types and fields
...
}
Is there any possibility to retrieve a concatenation of fields with the type ObservableCollection<DataElement>? Using LINQ I would do something like
var query = dbCollection
.AsQueryable()
.Select(x => new {
data = x
.OfType(typeof(ObservableCollection<DataElement>))
.SelectMany(x => x)
.ToList()
});
or alternatively
data = x.Where(y => typeof(y) == typeof(ObservableCollection<DataElement>)
.SelectMany(x => x).ToList()
Unfortunately .Where() and .OfType() do not work on documents, only on queryables/lists, so is there another possibility to achieve this? The document structure must stay the same.
Edit:
After dnickless answer I tried it with method 1b), which works pretty well for getting the fields thy way they are in the collection. Thank you!
Unfortunately it wasn't precisely what I was looking for, as I wanted to be all those fields with that specific type put together in one List, at it would be returned by the OfType or Where(typeof) statement.
e.g. data = [x.PartData , x.SensorData, ...] with data being an ObsverableCollection<DataElement>[], so that I can use SelectMany() on that to finally get the concatenation of all sequences.
Sorry for asking the question unprecisely and not including the last step of doing a SelectMany()/Concat()
Finally I found a solution doing this, but it doesn't seem very elegant to me, as it needs one concat() for every element (and I have more of them) and it needs to make a new collection when finding a non-existing field:
query.Select(x => new
{
part = x.PartData ?? new ObservableCollection<DataElement>(),
sensor = x.SensorData ?? new ObservableCollection<DataElement>(),
}
)
.Select(x => new
{
dataElements = x.part.Concat(x.sensor)
}
).ToList()
In order to limit the fields returned you would need to use the MongoDB Projection feature in one way or the other.
There's a few alternatives depending on your specific requirements that I can think of:
Option 1a (fairly static approach): Create a custom type with only the fields that you are interested in if you know them upfront. Something like this:
public class OnlyWhatWeAreInterestedIn
{
public ObservableCollection<DataElement> PartData { get; set; }
public ObservableCollection<DataElement> SensorData { get; set; }
// ...
}
Then you can query your Collection like that:
var collection = new MongoClient().GetDatabase("test").GetCollection<OnlyWhatWeAreInterestedIn>("test");
var result = collection.Find(FilterDefinition<OnlyWhatWeAreInterestedIn>.Empty);
Using this approach you get a nicely typed result back without the need for custom projections.
Option 1b (still pretty static): A minor variation of Option 1a, just without a new explicit type but a projection stage instead to limit the returned fields. Kind of like that:
var collection = new MongoClient().GetDatabase("test").GetCollection<Test>("test");
var result = collection.Find(FilterDefinition<Test>.Empty).Project(t => new { t.PartData, t.SensorData }).ToList();
Again, you get a nicely typed C# entity back that you can continue to operate on.
Option 2: Use some dark reflection magic in order to dynamically create a projection stage. Downside: You won't get a typed instance reflecting your properties but instead a BsonDocument so you will have to deal with that afterwards. Also, if you have any custom MongoDB mappings in place, you would need to add some code to deal with them.
Here's the full example code:
First, your entities:
public class Test
{
string _id;
public ObservableCollection<DataElement> PartData { get; set; }
public ObservableCollection<DataElement> SensorData { get; set; }
// just to have one additional property that will not be part of the returned document
public string TestString { get; set; }
}
public class DataElement
{
}
And then the test program:
public class Program
{
static void Main(string[] args)
{
var collection = new MongoClient().GetDatabase("test").GetCollection<Test>("test");
// insert test record
collection.InsertOne(
new Test
{
PartData = new ObservableCollection<DataElement>(
new ObservableCollection<DataElement>
{
new DataElement(),
new DataElement()
}),
SensorData = new ObservableCollection<DataElement>(
new ObservableCollection<DataElement>
{
new DataElement(),
new DataElement()
}),
TestString = "SomeString"
});
// here, we use reflection to find the relevant properties
var allPropertiesThatWeAreLookingFor = typeof(Test).GetProperties().Where(p => typeof(ObservableCollection<DataElement>).IsAssignableFrom(p.PropertyType));
// create a string of all properties that we are interested in with a ":1" appended so MongoDB will return these fields only
// in our example, this will look like
// "PartData:1,SensorData:1"
var mongoDbProjection = string.Join(",", allPropertiesThatWeAreLookingFor.Select(p => $"{p.Name}:1"));
// we do not want MongoDB to return the _id field because it's not of the selected type but would be returned by default otherwise
mongoDbProjection += ",_id:0";
var result = collection.Find(FilterDefinition<Test>.Empty).Project($"{{{mongoDbProjection}}}").ToList();
Console.ReadLine();
}
}

Retrieving Data from LINQ to SQL in JSON format?

I have a problem with Serialization of Data from database to JSON format. I'm using WebAPI 2 and Entity Framework 6. I've created with EF a Model. The database and the tables with content are even created.
When I use the code below I'm getting an error when I type http://localhost:54149/api/qr_group .
Controller:
private EfContext db = new EfContext();
// GET api/<controller>
public IEnumerable<QR_Group> GetGroups()
{
var result = from g in db.QR_Groups
select g;
return result.ToList();
}
I don't know how to use Newtonsoft.Json to serialize the table with the content in JSON format.
I've tried the following code instead of the code above:
public IQueryable<QR_Group> GetGroups()
{
var groupList = (from g in db.QR_Groups
select new
{
name = g.name,
code = g.code
}).AsQueryable();
var json = JsonConvert.SerializeObject(groupList);
return json; //error CS0029: Cannot implicitly convert type `string' to `System.Linq.IQueryable<RestApi.Models.QR_Group>'
}
I get the error CS0029.. How can I solve this to return the data in json? As reminder: The QR_Group entity has 3 columns (Id, name, code)
Specifically to your second function, JsonConvert.SerializeObject would just serialize any object into a JSON format string, which means you should return a string instead of an IQueryable<>.
So for the controller there are quite a few ways to return it back, like: In MVC, how do I return a string result?
EDIT:
Following code would be one way that should working:
Controller:
private EfContext db = new EfContext();
// GET api/<controller>
public ActionResult GetGroups()
{
var groupList = (from g in db.QR_Groups
select new
{
name = g.name,
code = g.code
}).AsQueryable();
return Content(JsonConvert.SerializeObject(groupList));
}
you didn't mention the error when you are returning list from the api
controller. as i assume that you are returning a database entity that
in simple case not allow you as json result, because your entity may
be linked with other entities in the database.
you can check this link for reference
Now modify your code to something like below. It is just to make you understand.
Define a Type say QR_Group_Return
public class QR_Group_Return{
public string name{ get; set;}
public string code{ get; set;}
// Some other properties will go here.
}
Now instead of returning IEnumerable<QR_Group> we will return IEnumerable<QR_Group_Return>
private EfContext db = new EfContext();
// GET api/<controller>
public IEnumerable<QR_Group_Return> GetGroups()
{
var result = (from g in db.QR_Groups
select new QR_Group_Return {
name = g.name,
code = g.code,
// map your other properties also
}).ToList();
return result;
}
Hope this helps

Obtain an array from an Object

I have the following class definition.
public class people
{
public string first_name { get; set; }
public string last_name { get; set; }
public DateTime date_of_birth { get; set; }
}
I've then created an array of people as follows:
people[] the_people = new people[3];
the_people[0].first_name="Tony";
the_people[0].last_name="Carrot";
the_people[0].date_of_birth=new DateTime(1959-03-16);
the_people[1].first_name="Joe";
the_people[1].last_name="Tomato";
the_people[1].date_of_birth=new DateTime(1963-06-2);
the_people[2].first_name="Tarina";
the_people[2].last_name="Wends";
the_people[2].date_of_birth=new DateTime(1982-11-22);
How can I store the first_names of the_people object in a new string array such that an output like the following is obtained. Is this possible via linq
string[] the_peoples_first_names=new string[3] {"Tony","Joe","Tarina"};
Similarly how would I obtain an array of date times to store the date of births of all people in a separate DateTime array.
What you are trying to do can be done with LINQ. What you are basically asking for is a projection.
MSDN describes a projection as this:
Projection refers to the operation of transforming an object into a new form that often consists only of those properties that will be subsequently used. By using projection, you can construct a new type that is built from each object. You can project a property and perform a mathematical function on it. You can also project the original object without changing it.
So we want to project the objects in your the_people array into a new array. The documentation recommends using the Select LINQ operator:
var the_people_names = the_people.Select(p => p.first_name);
What goes inside of the Select is a delegate, often in the form of a lambda expression or anonymous delegate.
But we aren't quite there yet. Select is just a deferred evaluation that creates an enumerable sequence. It does not return an array. To create an array, we use .ToArray():
var the_people_names_array = the_people.Select(p => p.first_name).ToArray();
You can use this approach to any property of people class, including the date of birth.
You can learn more about LINQ on MSDN on the LINQ about page.
var firstNames = the_people.Select(p => p.first_name).ToArray();
var dates_of_birth = the_people.Select(p => p.date_of_birth).ToArray();

RavenDB Map only index returns null values after AsProjection<T>

I have a next index:
public class TestIndex : AbstractIndexCreationTask<Resource>
{
public class Result
{
public string Caption { get; set; }
public string TestVal{ get; set; }
}
public TestIndex()
{
Map = resources => from r in resources
select new
{
Caption = r.Caption,
TestVal = r.Caption
};
}
}
And that's how I query it:
var data = session.Query<Resource, TestIndex>()
.Customize(x => x.WaitForNonStaleResults())
.AsProjection<TestIndex.Result>()
.ToList();
The problem is that after query TestVal property is null for each object, when Caption is filled with expected value.
If you want to do a projection from the index, you need to store that value
I had similar problem, query on the index still retruned null values. It turned out that i did to fast test - after each program running index was also runing and it had no enough time do biild up. In this case sulution is use customization.WaitForNonStaleResultsAsOfNow():
Query<ResultType,IndexType>()
.Customize(customization => customization.WaitForNonStaleResultsAsOfNow()) //this is imprtant when you using quick tests, not in production server
.Where(...).AsProjection<ResultType>
You also need remember about storing data from index to DB and use at the end in index class:
StoreAllFields(FieldStorage.Yes);

Categories

Resources