I need to compare two structures to see if they are equals. What is the best way to do in dotnet 5?
I saw several simpler structures, no idea of the best way to do it.
public sealed record ProductionFlow
{
public string FlowName { get; init; }
public string FlowDescription { get; init; }
public OperationFlow[] Operations { get; init; }
}
public sealed record OperationFlow
{
public int Group { get; init; }
public int[] Equipment { get; init; }
public int Task { get; init; }
public bool Optional { get; init; }
}
I Do need to compare the array of record "Operation". All array with all properties must be equal.
Notice that we have on array of array beyond another properties in "OperationFlow" record.
Thanks!
Related
I have a list of objects(FilesInfo) that contain objects(LanguageInfo). LanguageInfo is an object that contains further objects for LanguageName and LanguageId. The LanguageName and LanguageId is also an object, that (finally) contains a string value.
I want to group the list of files by the language.
This doesn't work (I suppose a matter of by value/reference comparing magic):
var languageGroupings = data.FilesList.GroupBy(ufi => ufi.LanguageInfo);
(although this is what I am essentially trying to achieve)
This does:
var languageGroupings = data.FilesList.GroupBy(ufi => ufi.LanguageInfo.LanguageName.Value);
Now, the issue is that I don't know whether the LanguageInfo will contain LanguageName, or LanguageCode (or one of other similar properties, ClientLanguageName, ClientLanguageCode) - which is why I basically want to group the files based on all of the properties values nested in LanguageInfo.
How do I do that?
These are the (minimized) classes:
public class UniversalLanguageInfo
{
public int UniversalLanguageInfoId { get; set; }
public UniversalDataElement LanguageCode { get; set; }
public UniversalDataElement LanguageId { get; set; }
public UniversalDataElement LanguageName { get; set; }
public UniversalDataElement ClientLanguageCode { get; set; }
public UniversalDataElement ClientLanguageName { get; set; }
}
public class UniversalDataElement
{
public string Value { get; set; }
public DataFormats DataSource { get; set; }
public string OriginalName { get; set; }
public bool IsExcluded { get; set; }
}
public class UniversalFileInfo
{
public virtual UniversalDataFormat UniversalDataFormat { get; set; }
public UniversalLanguageInfo LanguageInfo { get; set; }
public UniversalDataElement FileName { get; set; }
public UniversalDataElement Id { get; set; }
public UniversalWordcount Wordcount { get; set; }
}
Implement Equals(object) and Equals<T> for your UniversalLanguageInfo and UniversalLanguageElement classes. When you do the GroupBy() you will get the results you're looking for.
In your implementations of these methods, you can choose the level to which they are "equal". In the case you describe, that's a "deep equals", which means you need to implement equals for the entire graph except for the objects in that graph that you're sure have an Equals that is suitable. At each level call the Equals of all the children.
As meJustAndrew below suggests, you will have to implement GetHashCode() because that is good practice. Gian Paolo suggests going the comparer route, which is especially useful if you aren't able to modify the classes in your object graph or don't want general equality to be universally available.
How to: Do nested lists in sqlite-net-extensions
Answer Found: Keeping the question as an example of how to do it.
The problem i encountered was not sqlite-net-extensions related, but i'm keeping the question for context.
[Old Question]
I've got a problem with TwinCoders SQLite-net extensions.
I'm trying to insert a Series object into my database:
I'm using the Db.InsertWithChildren(SelectedSeriesObject,recursive:true) method.
The Series object is added accordingly with it's attributes.
All the Episodes are added as well, no problems there.
The problem is the BaseSeason.
It will only insert one Season object, which is (for some reason) the last Season Object of the list of Seasons in the Series
public class BaseSeries : BaseMedia
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
[Indexed]
public int ShowId { get; set; }
public string FirstAirDate { get; set; }
public string LastAirDate { get; set; }
public string Status { get; set; }
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<BaseSeason> Seasons { get; set; }
/// <summary>
/// TvShow = 0, Anime = 1
/// </summary>
public int SeriesType { get; set; }
}
public class BaseSeason
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
[ForeignKey(typeof(BaseSeries))]
public int SeasonId { get; set; }
public int SeasonNumber { get; set; }
public int NumberOfEpisodes { get; set; }
public string Plot { get; set; }
public string Poster { get; set; }
public string AirDate { get; set; }
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<BaseEpisode> Episodes { get; set; }
[ManyToOne]
public BaseSeries BaseSeries { get; set; }
}
public class BaseEpisode
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
[ForeignKey(typeof(BaseSeason))]
public int EpisodeId { get; set; }
public string Title { get; set; }
public string Plot { get; set; }
public string Poster { get; set; } //still path
public string AirDate { get; set; }
public int EpisodeNumber { get; set; }
public int SeasonNumber { get; set; }
public string SeriesName { get; set; }
[ManyToOne]
public BaseSeason BaseSeason { get; set; }
}
Is there anyone with experience regarding nested relationships in sqlite-net-extensions that knows how to make this work or see what i did wrong?
So regarding writing nested lists in sqlite-net-extensions:
My problem turned out the be related to how I handle the creation of these objects, this is by no means related to sqlite-net extensions. So my bad!
Which means that the questions example is valid and works. (I tested it of course)
Setting up the entities for the database:
The example shown in my question, with a Series class, Season class and Episode class, is the correct way of setting it up.
Inserting into the database:
If you're wondering how to insert an object similar to my Series object (with nested lists), use:
db.InsertWitchChildren(yourObject, recursion: true)
Here's an extended example:
public void AddSeries()
{
MediaDB.db.CreateTable<BaseSeries>();
MediaDB.db.CreateTable<BaseSeason>();
MediaDB.db.CreateTable<BaseEpisode>();
MediaDB.db.InsertWithChildren(SelectedSeries, recursion: true);
}
Side Note:
The example uses a static property on class with the connection string. Like so:
public class MediaDB
{
public static SQLiteConnection db => new SQLiteConnection(new SQLitePlatformGeneric(),"Media.db");
}
Refrain from doing this it is not really the best thing to do, since you should use using for the SQLiteConnection, making sure it's disposed once you're done with it.
more info on: sqlite-net-extentions
[UPDATE]: Further expansion of handling nested lists in sqlite-net extensions:
Deleting tables with children:
This is quite simple, but i spent a good hour and half figuring it out anyways.
Just use:
For lists/arrays: db.DeleteAll(yourCollection, recursion: true)
For single objects: db.Delete(yourObject, true);
As an exmaple: here's my implementation of a method that will delete a List
(BaseSeries is the class shown in the original question question):
public static void RemoveCollection<T>(List<T> collection)
{
using (db)
{
if (typeof(T) == typeof(BaseMovie))
{
db.DeleteAll(collection);
}
if (typeof(T) == typeof(BaseSeries))
{
db.DeleteAll(collection, recursion: true);
}
}
}
The BaseMovie class is a simple single entity, recursion is not needed since it holds no children.
I have objects that are defined this way:
class BFull
{
public string ImageID { get; set; }
public List<string> Tapes { get; set; }
}
class OptSet
{
public int SetID { get; set; }
public List<string> Tapes { get; set; }
public List<string> Images { get; set; }
}
The BFull object is DB defined and I can't alter it much. The second one is the wanted result of my actions. And the problem is:
I need to optimize those BFulls into OptSets with a limitation that any given OptSet can have max 24 distinct tapes and consist only complete BFulls. Can anybody help how to achieve that?
I'm looking for a way to "divide" multiple operations that needs to be done so as to gain efficiency.
Let me put an example to explain my need.
Say that I have this object:
public class CardInfo
{
public int mCardID { get; set; }
public string mCardName { get; set; }
public int? mCardNumber { get; set; }
public string mCardColor { get; set; }
(...)
}
Each objects may be linked to a price list object:
public class PriceListInfo
{
public int mPriceListId { get; set; }
public int mPriceProviderID { get; set; }
public PriceProviderInfo mPriceListProvider { get; set; }
public int mCardID { get; set; }
public CardInfo mCard { get; set; }
public decimal? mPriceLow { get; set; }
public decimal? mPriceMid { get; set; }
public decimal? mPriceHigh { get; set; }
}
Now I have a process which task is to actually get a list of cards and build the price list of each cards, like this:
List<CardInfo> listCards = mCardManager.ListCardsForCardSet(_cardSetID);
foreach(var card in listCards)
{
List<PriceListInfo> listPrices = mPriceManager.ListPricesForCar(card);
}
Something quite simple, however if the list of cards contains more than 500 items, it will take a while. I am wondering (and since I don't know much about Asp.Net, it is why I am asking the question) if there's a way to divide the list by an [X] number and then launch many times the List<PriceListInfo> listPrices = mPriceManager.ListPricesForCar(card); line? Or is there a way to make these operation asynchronously? (please pardon my ignorance, thank you.) Can anybody explain how could I proceed, and if you could provide an example, I'd be more than happy.
I am creating a drivers license object in my project, that employees will all have one of their own linked to their unique clock number. I have a separate table in my database for the driving license but in the future more types of vehicles will need to be added, is there anyway to do this without re-coding?
the columns in my database are the same as the attributes for the class below
public class LicenseDTO
{
public int ClockNo { get; set; }
public bool CBalance { get; set; }
public bool MR16 { get; set; }
public bool OrderPicker { get; set; }
public bool Reach { get; set; }
public bool Pedestrian { get; set; }
public bool Lorry { get; set; }
public bool Sweeper { get; set; }
public bool Washer { get; set; }
}
EDIT
I have tried to create this the best I could but I feel like it's really long winded and can be done a more efficient way. Here's an updated version of my code.
public class LicenseDTO
{
public int ClockNo { get; set; }
public List<Common.VehicleTypeDTO> Vehicles { get; set; }
}
public class VehicleTypeDTO
{
public string VehicleType { get; set; }
public bool Allowed { get; set; }
}
private void btnClockCardIn_Click(object sender, EventArgs e)
{
Common.LicenseDTO License = new Common.LicenseDTO();
List<Common.VehicleTypeDTO> Vehicles = new List<Common.VehicleTypeDTO>();
Common.VehicleTypeDTO CBalance = new Common.VehicleTypeDTO();
Common.VehicleTypeDTO MR16 = new Common.VehicleTypeDTO();
License.Vehicles = Vehicles;
CBalance.VehicleType = "CBalance";
CBalance.Allowed = true;
MR16.VehicleType = "MR16";
MR16.Allowed = false;
License.Vehicles.Add(CBalance);
License.Vehicles.Add(MR16);
foreach (Common.VehicleTypeDTO Vehicle in License.Vehicles)
{
MessageBox.Show(Vehicle.VehicleType + " " + Vehicle.Allowed);
}
}
Why not to create a table with the types of vehicles? In the future you can access to your table and insert more types.
public class VehicleTypeDTO
{
public int Id{ get; set; }
public string Name{ get; set; }
}
public class LicenseDTO
{
public int Id { get; set; }
public List<VehicleTypeDTO> VehicleTypes { get; set; }
}
You should have made an entity LicenseDTO with the attributes ClockNo and CBalance alongside an array of the type Vehicle. which will be an interface. the interface Vehicle can define any common methods the vehicles have. and all future vehicles will have to implement the interface. that way you dont have to change any code. Your current code cannot be "changed" without editing. You could try to extend your LicenseDTO class with another entityclass which implements the above interface. but there isnt much more you can do without editing.
If you want maintainability use interfaces, repository patterns, abstract classes and dependency injection to start with.
Instead of having multiple bit columns in your database to indicate different types of vehicles, have a single VehicleType table. Then you can add as many different vehicle types as you like and use the VehicleTypeID to uniquely identify them. You can then add more and more vehicle types to the table without having to write more code.
VehicleType
VehicleTypeID int
VehicleTypeName varchar(50)
public class LicenseDTO
{
public int ClockNo { get; set; }
public int VehicleTypeID { get; set; }
}
If you want to have multiple types of vehicles against a single ClockNo then use a list of int:
public class LicenseDTO
{
public int ClockNo { get; set; }
public List<int> VehicleTypes { get; set; }
}
Alternately you could have a reference to the VehicleType objects instead of just the ID's.