list<T> - sql like statements for retrieving data - c#

I have the following table
public class QTable
{
public string QID { get; set; }
public string QNO { get; set; }
public string Q1 { get; set; }
public string Q2 { get; set; }
public string opt1 { get; set; }
public string opt2 { get; set; }
public string opt3 { get; set; }
public string opt4 { get; set; }
public string Answer { get; set; }
public string Remarks { get; set; }
public string KnowledgeArea { get; set; }
public string Hints { get; set; }
public string Section { get; set; }
public string ToughLevel { get; set; }
public string DateCreated { get; set; }
public string Category { get; set; }
public string DeleteMe { get; set; }
}
QID is my primary key.
I have the
List<Qtable> qtableList = <list of all values of qtable from a query>
I need to find a particular QID and take other fields for manipulation.
Is there a SQL statement like structure to manipulate these things for a list?

You can use to get the item you want
Qtable item = qtableList.FirstOrDefault(x=>x.QID == id);
Just be aware that if the QID dont exists on the list and you try to access one of its properties, an 'Object reference is not an instance of an object exception' will be thrown, since you are trying to access a null object.
To prevent that, check if the return is differente of null prior to access and modify the properties you want.

In C# the best sql ike approach is just simply use linq, it's maded to handle this kind of request.
The basic syntax is:
var query = from qt in qtableList
where qt.QID == "1"
select qt;
This is basically returning the first pk element of your data.
Insert, update and other basic sql operations working as well.
More about on this:
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/basic-linq-query-operations

Related

Entity Framework Core with undefined/dynamic columns

I have a db with some tables in which items contains some localized string. The plan is to have an ID to a dedicated "Localization" table.
public class User
{
public int Id {get; set; }
public string Name { get; set; }
public Localization Signature { get; set; }
}
public class Item
{
public int Id {get; set; }
...
public Localization Title { get; set; }
}
public class Localization
{
public int Id { get; set; }
public string En { get; set; }
public string Fr { get; set; }
public string De { get; set; }
}
This works. But the goal is now to have a "dynamic" list of languages, so we could easy extend the localization to other languages.
I can solve this with a JSON field in which I serialize the languages string, but it has the disadvantage to lose the readability in any DB Viewer. So if possible, I would like to have real columns.
Is there any way to solve this use case with EF Core ?
I'd approach this not by adding columns to the database (which requires a change to the DB structure) but by adding rows:
public class Item
{
public int Id {get; set; }
...
public string Title { get; set; }
}
public class Localization
{
public int Id { get; set; }
public int ItemId { get; set; }
public string LanguageCode { get; set; }
public string Text { get; set; }
}
Then load item's title along the lines of:
item.Title = context.Localizations
.Where(l => l.ItemId == item.Id && l.LanguageCode == "en")
.FirstOrDefault();
(You can also load Title in the same query where you load Item... that query is meant to be illustrative of the concept).

Accessing a single field in a foreach using Linq Dapper

I am using dapper and I want to use Linq to be able to update a single field called status in one table I am trying to use.
public async Task<Int32> ProcessUnprocessedTransactions(IEnumerable<BomComponentData> items)
{
IEnumerable<BomComponentData> _itemstoBeProcesed = items.Where(w => w.Status == (int)BomStatus.Scanned);
foreach (BomComponentData item in _itemstoBeProcesed)
{
item.Status = (int)BomStatus.Completed;
}
return await database.UpdateAsync(_itemstoBeProcesed);
}
My class is as follows:
public class BomComponentData
{
public int Sequence { get; set; }
public string BOMShortName { get; set; }
public string OperationName { get; set; }
public long BomId { get; set; }
public long BOMLineID { get; set; }
public long StockItemID { get; set; }
public string BomLineType { get; set; }
public int Quantity { get; set; }
public long UnitID { get; set; }
public decimal? MultipleOfBaseUnit { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public string Barcode { get; set; }
public long ProductGroupID { get; set; }
public string ProductGroupCode { get; set; }
public int Status { get; set; }
public int BinLocation { get; set; }
public string BinName { get; set; }
public string UOM { get; set; }
public int CalculatedValue { get; set; }
public int BomPickedCount { get; set; }
public int TotalLeftTopick
{
get { return Quantity - BomPickedCount; }
}
public enum BomStatus
{
Listed=1,
Scanned=2,
Confirmed=3,
Processed=4,
Completed=4,
InVisible=5
}
public override string ToString()
{
return Code;
}
}
But it does not work if I use a foreach like above. I am sure it should update the items properly but I think that because I'm going through singular items in my foreach and my list in the update it's not updating correct.
All I want to do is mark the items as completed and ready for transfer, I am doing so by the status column and an int enum.
Maybe I am missing a declaration of what is my primary key?
Edit 2
When I use a key declaration of the primary key I get the following:
Unhandled Exception: System.AggregateException: One or more errors occurred. (Constraint
Edit 3
I have set key of my class but as you see I have auotincrement on my db and it still crashes. How should insert be handled?
Edit 4
For example I am inserting into the database as follows. Shouldn't this work?
List<BomComponentData> _bomList = new List<BomComponentData>();
_bomList.Add(new BomComponentData { Sequence = 1, Barcode = "0000000001498", BinLocation = 23, BinName = "A", BOMShortName = "GYNE-TXX", OperationName = "Example Product", Code = "TB9175CEA", Name = "Tiburon Peri/Gynae Pack-10", Quantity = 1, UOM = "Each" });
await database.InsertAllAsync(_bomList,true);
I have placed the tag key for the update that works ok but when I attempt to do an insert with the key it doesn't it says constraint error but the update works. Does anybody no how i can solve both the insert and update in Dapper contrib.
You are using Dapper.Contrib and this extension requires that you decorate your class with some attributes to help in the automatic handling of your data.
In particular for an Update method you need to define the Table attribute and the Key attribute to identify the primary key
[Table ("BomComps")]
public class BomComponentData
{
// [ExplictKey]
[Key]
public int Sequence { get; set; }
....
Here, for example, I have added the attribute Table to set a possible table name on the database, but if the name of the physical table matches the name of the class then you can omit the attribute. Also I have added the Key attribute to set the property that contains the primary key of your table (so the statement that updates your records could be formed with the proper WHERE condition).
Notice that the Key attribute should be used if the column has an Identity property set to yes while, if not, you use the ExplicitKey attribute to signal that the primary key is defined by your code.
This was actually the issue I had to decoate my class with the following Leaving this here so that anyone else has issue I was using the pcl libary but for some reason dapper contribe did not detect the key element it had to be declared as follows.
[SQLite.PrimaryKey, SQLite.AutoIncrement]
public class StockTransferArgs
{
[SQLite.PrimaryKey, SQLite.AutoIncrement]
public int StockTransferArgsId { get; set; }
public long StockItemID { get; set; }
public string Code { get; set; }
public string OperationName { get; set; }
public string Description { get; set; }
public decimal Quantity { get; set; }
public long SourceWarehouseID { get; set; }
public string SourceBinName { get; set; }
public long TargetWarehouseID { get; set; }
public string TargetBinName { get; set; }
public string Reference { get; set; }
public string SecondReference { get; set; }
public string BarCode { get; set; }
public int Status { get; set; }
}

Returning all entries in a C# list matching an int

I have a list that has the following:
class GetMyList
{
public int searchInt { get; set; }
public string Name { get; set; }
public string Type { get; set; }
public string Retype { get; set; }
public string Time { get; set; }
public string City { get; set; }
public DateTime dateHere { get; set; }
}
This list could have multiple entries for each int (ie the searchInt 1 could have an entry for 4/11/2017 and another for 4/12/2017).
How do I return ALL of the entries that match the searchInt of 1 in my example above? Preferably so I can just access the dateHere field but it would be nice to know the others, if that matters.
You could simply utilize Linq.
var filter = collection.Where(search => search.searchInt == 1);
The Where would in essence match on a predicate, so in this case all items that evaluate to true in my statement, will be returned.

with list of objects updating wrongly

Here is the class
public class CartManage
{
public int prodId { get; set; }
// public string prodId { get; set; }
public int qty { get; set; }
public string color { get; set; }
public string size { get; set; }
public string Name { get; set; }
public string ShortDescription { get; set; }
public string Specification { get; set; }
public double Price { get; set; }
public string skew { get; set; }
public string weight { get; set; }
public string maxqty { get; set; }
public string productimage { get; set; }
public string prd_vendor_id { get; set; }
public string prdDeliveryDays { get; set; }
public bool GiftingEnabled { get; set; }
public int GiftingId { get; set; }
}
I use this to manage cart in my website i.e List < CartManage > prodList_temp. Now when a person increase the quantity of an item in cart. I add another object in the list(I used to just increase the quantity of the object but due to some functionality i have to implement i need separate objects). I did this by doing a linq query on the list and just adding the result to cart.
var session_updating_data = prodList_temp.Where(p => p.skew == reqired_skew);
prodList_temp.Add(session_updating_data.FirstOrDefault());
The problem im having is that after inserting when ever change anyting in one of the copies the changes are reflected in all the copies. for example i have two quantity of item A, i.e the cart contains two objects containing details of item a created as shown above. Now if I change the giftingEnabled property of any one of the objects it gets reflected in both. Now i found a work around for this by creating a new object. but i would like to know why this weird phenomenon is happening for future reference.
var session_updating_data = prodList_temp.Where(p => p.skew == reqired_skew);
prodList_temp.Add(session_updating_data.FirstOrDefault());
You are passing a reference to that object to your list, so any change in the object will be reflected everywhere. Where as when you create a new object, it's a separate instance.

C# Linq search inside object linked property

i'm trying to do some search inside some attributes of my object set but i'm getting some trouble on the right way to mount my linq query, i have my VT_Video class which has its attributes and some linked objects
public partial class VT_Video
{
public int ID { get; set; }
public string title { get; set; }
public string description { get; set; }
public virtual ICollection<VT_VideoTag> VT_VideoTag { get; set; }
}
public partial class VT_VideoTag
{
public int ID { get; set; }
public int tagID { get; set; }
public int videoID { get; set; }
public virtual VT_Tag VT_Tag { get; set; }
public virtual VT_Video VT_Video { get; set; }
}
public partial class VT_Tag
{
public int ID { get; set; }
public string name { get; set; }
public virtual ICollection<VT_VideoTag> VT_VideoTag { get; set; }
}
What i want to accomplish is search a user given word inside my Video collection by VT_Video.title, VT_Video.description and also by VT_Video.VT_VideoTag.VT_Tag.name, what i managed to do so far is only search the title and description:
var myVideos = db.VT_Video.Include("VT_VideoTag")
.Include("VT_VideoTag.VT_Tag")
.Where(vid =>
vid.descricao.Contains(strBusca) ||
vid.titulo.Contains(strBusca)).ToList();
Now, i know i can do what i want with some foreach and extra code but i wondered if it would be possible to do it using linq and also keep my code clean.
Thanks.
I have not worked with LINQ to SQL much, but it seems like .Any() would satisfy your requirement:
var myVideos = db.VT_Video.Include("VT_VideoTag")
.Include("VT_VideoTag.VT_Tag")
.Where(vid =>
vid.descricao.Contains(strBusca) ||
vid.titulo.Contains(strBusca) ||
vid.VT_VideoTag.Any(tag => tag.name.Contains(strBusca))).ToList();
Notice I added this clause:
vid.VT_VideoTag.Any(tag => tag.name.Contains(strBusca))
Which returns true if any tag in the collection has a name that contains your search string.

Categories

Resources