C# Find and edit single object on list - c#

public class kDrinki
{
public int id {get; set;}
public string nazwa { get; set; }
public string skladniki { get; set; }
public string opis { get; set; }
public string sciezka { get; set; }
public kDrinki(int _id, string _nazwa, string _skladniki, string _opis, string _sciezka)
{
id = _id;
nazwa = _nazwa;
skladniki = _skladniki;
opis = _opis;
sciezka = _sciezka;
}
}
I have got that class. I created List lst_pDrinkow of object and added some form XML. I don't know how to find only single object (using object id not list id) from list and edit all his data(not only single parameter).

You could try something like this:
var obj = lst_pDrinkow.SingleOrDefault(x=>x.id==Id);
Where Id is the id of the object you are looking for.
If there is an object with the supplied Id, you will get it. Otherwise, the result would be null.
Once you get the object you want, it's very easy to update it's data.
if(obj!=null)
{
obj.nazwa = "new value";
// update the values of the other properties with the same way.
}
Update
While it is not your case, I have to note here that if there are more than one objects with the supplied Id, then you will get an exception. We usually use the SingleOrDefault, when we are sure that the object we are looking for it is unique if at all exists.
More formally:
Returns the only element of a sequence, or a default value if the
sequence is empty; this method throws an exception if there is more
than one element in the sequence.
as it is stated here.

List<kDrinki> items = new List<kDrinki>();
var tmp1 = items.SingleOrDefault(a => a.id == 10);
tmp1.skladniki = "new value";
var tmp2 = items.SingleOrDefault(a => a.opis.Contains("some strings"));
tmp2.skladniki = "new value2";

Related

How to convert a linq query to ToList() to use extended properties

private IQueryable<SubjectDataViewModel> GetData()
{
var subject = this.DbContext.Subjects.AsQueryable(); //sql view
var data =
from subject in subjects
let treatment = this.DbContext.TreatmentFactor.FirstOrDefault(x => x.TreatmentFactorId == subject.ActiveTreatmentFactor)
select new SubjectDataViewModel
{
Name = subject.Name,
Gender = subject.Gender,
Version = subject.Version.IsEnumToValueDisplay() // extented method which displays enum DisplayName property into string
};
return data.AsQueryable();
}
This is the View Model i am populating into as per query above .
public class SubjectDataViewModel
{
public string Name {get;set;}
public string Gender {get;set;}
public string Version {get;set;} // string type return
}
This is Subject Sql View
public class Subjects
{
public string Name {get;set;}
public string Gender {get;set;}
public Version Version {get;set;} // enum return type
}
Enum that is used for Version . Need to Used the ToEnumDiplayValue() extended method in the linq query to pull the Diplay Name i.e Original instead of Database value which is 0 and 1 which will show first or second.
public enum Version
{
[Display(Name = "Original")]
first= 0,
[Display(Name = "Not Original")]
second = 1,
}
So I want to get the DisplayName for the Version which can be done by using our own extended method that using reflection to get the Display name from the enum .
But i cannot use it in the in memoryobject . It has to be converted to .ToList() for.
That is what i want. I hope i am clear. Thank you for your time .
As of now my code will throw ERROR message since i cannot use extended property in Linq.
Try
private IQueryable<SubjectDataViewModel> GetData()
{
var subject = this.DbContext.Subjects.AsQueryable(); //sql view
var data =
from subject in subjects
let treatment = this.DbContext.TreatmentFactor.FirstOrDefault(x => x.TreatmentFactorId == subject.ActiveTreatmentFactor)
select new SubjectDataViewModel
{
Name = subject.Name,
Gender = subject.Gender,
VersionEnum = subject.Version // Version Enum
};
return data.AsQueryable();
}
Use below code to convert GetData() into the list afterwards use IsEnumToValueDisplay() method.
var list = GetData().ToList();
foreach (var item in list)
{
item.Version = item.VersionEnum.IsEnumToValueDisplay(); // Get value from Version Enum
}
Change Model SubjectDataViewModel
public class SubjectDataViewModel
{
public string Name {get;set;}
public string Gender {get;set;}
public Version VersionEnum {get;set;}
public string Version {get;set;}
}

Universal app object distinct by variable

I have a problem:
In my code I have this obj
//:extension for being saved locally
public class FOO
{
public int ID { get; set; }
public string STRINGVALUE{ get; set; }
public int INTVALUE { get; set; }
//ecc..
//SelectAll() method which returns all FOO in local DB
}
Now what I want is, in some cases, to pick all FOO obj where STRINGVALUE (or INTVALUE) is not duplicated.
For example:
List<FOO> fooes = new FOO().SelectAll();
List<FOO> uniqueIntFoo = fooes.distinct(); //here i have to set the clause
There is the Distinct() method in Linq, but it compare the entire item, not a single variable of it.
Any of you know how can I do it?
What about grouping the results, something like:
By both Int and StrValue:
var uniqueItems = fooes.GroupBy(x => new{x.IntVal, x.StrVal});
By IntVal:
var uniqueItems = fooes.GroupBy(x => x.IntVal);
Edit, as suggested by question's author:
fooes.GroupBy(x => x.INTVALUE).Select(y => y.First()).Distinct().ToList();

Dapper: Not able to parse string from dbf(Error parsing column)

I want to use dapper to query over dbf files. In my file example.dbf I have two columns:
Value - type NUMERIC
Name - type CHARACTER
I write class ExampleDbf
class ExampleDbf
{
public int Value { get; set; }
public string Name { get; set; }
}
Now I want to write two simple query
var listOne = connection.Query<ExampleDbf>("SELECT value FROM Example");
var listTwo = connection.Query<ExampleDbf>("SELECT name, value FROM Example");
ListOne are OK but when I execute listTwo I Have following System.Data.DataException:
Additional information: Error parsing column 0 (name=System.Byte[] - Object)
When I use standard DataReader I must write something like that
example.name = System.Text.Encoding.ASCII.GetString((byte[])reader["name"]).Trim();
Of course I may write something like this:
class ExampleDbf2
{
public int Value { get; set; }
public byte[] Name { get; set; }
public string StringName
{
get
{
return System.Text.Encoding.ASCII.GetString((byte[])Name ).Trim();
}
}
}
So now it works
var listTwo = connection.Query<ExampleDbf2>("SELECT name, value FROM Example");
But this solution is very ugly, maybe someone have better solution.
You could always return a dynamic, then map it to your object and perform the transformation operation during object initialization.
var listTwo = connection.Query<dynamic>("SELECT name, value FROM Example")
.Select(x => new ExampleDbf
{
Value = x.value,
Name = System.Text.Encoding.ASCII.GetString((byte[])x.name).Trim()
}).ToList();

Remove Item From Object SubList (LINQ)

I have an object that looks like this :
public class Consortium
{
public string Id { get; set; }
[JsonConverter(typeof(EnumDescriptionConverter))]
public SourceType Type { get; set; }
public List<UserLibrary> Branches { get; set; }
}
Each Consortium has a list of UserLibrary's associated with it, and that class looks like this :
public class UserLibrary
{
public string LibraryId { get; set; }
public string RetailerId {get; set;}
public string UserId { get; set; }
public string Name { get; set; }
public DateTime CreatedAt { get; set; }
}
I have a method which will allow the user to remove a library from one of their consortium (note: There may be many branches associated to the consortium).
However, I'm only being supplied a LibraryId, so I'm forced to traverse their list of Consortium, find which one contains the given id, then iterate over the branches and remove the one that matches the id.
Here is how I'm currently accomplishing this :
// Get the current list of consortiums
var user = _mediator.Send(new GetUserProfileCommand { UserProfileId = _principle.UserProfileId });
var userConsortia = user.SavedConsortia;
// the consortium to remove the library from
var branchToRemove = _libraryService.GetLibrary(id);
var consortRemove = new UserConsortium();
foreach (var userConsortium in userConsortia)
{
if (userConsortium.Branches.FirstOrDefault(c => string.Equals(c.LibraryId, id, StringComparison.OrdinalIgnoreCase)) != null)
{
consortRemove = userConsortium;
}
}
// if the consortium id is null, something is f*
if (consortRemove.Id == null)
{
return new JsonDotNetResult(HttpStatusCode.BadRequest);
}
// first remove the consortia
userConsortia.Remove(consortRemove);
// remove the branch from the consortium
consortRemove.Branches.RemoveAll(ul => string.Equals(ul.LibraryId, id, StringComparison.OrdinalIgnoreCase));
// add it back in without the branch
userConsortia.Add(consortRemove);
Question :
Is there a LINQ expression I'm missing here that can help me consolidate this logic, or is there a better way of doing this?
Yes, there are a few approaches you can take depending on taste. The easiest way to simplify what you've got would be this:
var branchToRemove = _libraryService.GetLibrary(id);
// .Single() will throw an exception unless there is one and only one match.
var consortRemove = userConsortia.Single(
c => c.Branches.Any(
b => string.Equals(b.LibraryId, id, StringComparison.OrdinalIgnoreCase));
// remove the consortia
userConsortia.Remove(consortRemove);
Why not something like this? It looks to me from your code that you want to remove the targeted "removal branch" from all consortiums in you collection.
foreach (UserConsortium userConsortium in userConsortia)
{
userConsortium.Branches.RemoveAll(c => string.Equals(c.LibraryId, id, StringComparison.OrdinalIgnoreCase));
}

DataGridView not displaying values using LINQ

It's very simple for the user.
They select the type of part, manufacturer from a ComboBox, and search the part code in a text box. Click search and the results return in a DataGridView.
Code:
var mType = CmbType.SelectedItem.ToString();
var mManufacturer = CmbMfr.SelectedValue.ToString();
var mCode = Convert.ToString(TxtProductCode.Text);
switch (mType)
{
case "Faucets":
var faucets = Resources.Accessor.SearchFaucets(mManufacturer, mCode);
DgInventory.DataSource = faucets;
break;
case "Parts":
var parts = Resources.Accessor.SearchParts(mManufacturer, mCode);
DgInventory.DataSource = parts;
break;
}
Accessor Code:
public static List<TblFaucets> SearchFaucets(string mId, string mCode)
{
var dataConnect = new PxLinqSqlDataContext();
return (from f in dataConnect.GetTable<TblFaucets>()
where (f.Mfr == Convert.ToInt32(mId))
where (f.Code == mCode)
select f).ToList<TblFaucets>();
}
What "messes up" is the results:
ID: correct
Mfr: is the ID from its table, not the name
Code: Correct
Description: correct
Price: correct
Date: correct
Manufacturer: I don't know why this is even here, its result is "PXDB.TblManufacturers
First, PXDB.TblManufacturers seems to be a relation from tblFaucets to tblManufactureres.
Mfr seems to be the foreignKey value within your faucets table refering to a manufacturer.
You may try creating an anonymous type holding only those data you want to. Within your select clause pick your data - as well as any relational data.
public static List<DisplayFaucet> SearchFaucets(string mId, string mCode)
{
var dataConnect = new PxLinqSqlDataContext();
return (from f in dataConnect.GetTable<TblFaucets>()
where (f.Mfr == Convert.ToInt32(mId))
where (f.Code == mCode)
select new DisplayFaucet () { // create anonymous object
ID = f.ID, // only holding the data you want to
Manufacturer = Manufacturer.Name, // assuming there is property Name within your manufacturer table?!
Code = f.Code,
Description = f.Description,
Price = f.Price,
Date = f.Date
}).ToList();
}
Add another class to hold your data to display
public class DisplayFaucet
{
public int ID { get; set; }
public string Manufacturer { get; set; }
public string Code { get; set; } // check type
public string Description { get; set; }
public doublePrice{ get; set; } // check type
public DaetTime Date { get; set; } // check type
}
Note that SearchFaucets(..) may no longer return items of type tblFaucet! Instead I created a new class. This one contains all data which should be displayed!

Categories

Resources