Consolidate/Merge data from TWO IEnumerable Lists into ONE - asp.net

I have following domain objects in my application:
[Serializable]
public class Supplier
{
public virtual string SupplierType { get; set; }
public virtual string SupplierCode { get; set; }
public virtual string Name { get; set; }
public virtual string Description { get; set; }
public virtual string Rating { get; set; }
public virtual string WebsiteURL { get; set; }
public virtual IList<Address> Address { get; set; }
}
[Serializable]
public class CargoSupplier : Supplier
{
public virtual IList<Image> Images { get; set; }
public virtual string OpeningTime { get; set; }
public virtual string ClosingTime { get; set; }
public virtual IList<Product> Products { get; set; }
}
I have to goto two seperate repositories for getting descriptive content (from database) and pricing (from external webservice) and will have two seperate enumerations populated with data (descriptive content & pricing):
IEnumerable<CargoSupplier> cargoSuppliers_Pricing
IEnumerable<CargoSupplier> cargoSuppliers_Content
cargoSuppliers_Content will have all fields populated with data EXCEPT IList<Product> and cargoSuppliers_Pricing will have SupplierType, SupplierCode and IList<Product> fields populated with data. Combination of "SupplierType" amd "SupplierCode" would be the key.
Now I have to merge the content and pricing into one enumeration so I can return IEnumerable<CargoSupplier> cargoSuppliers to my Controllers & Views. What is the best way to merge/consolidate these two lists into one?

Are you looking for Union or am i missing something in the question?
var mergedList = list1.Union(list2).ToList();
remember to import the System.Linq namespace

It sounds like you don't want one list that just contains all the items in either list - it sounds like you need to merge individual items. Something like this:
var query = from pricing in cargoSuppliers_Pricing
join content in cargoSuppliers_Content
on pricing.SupplierCode equals content.SupplierCode
select new CargoSupplier
{
// Copy properties from both objects here
};
Within the "select" part you would take the pricing parts from "pricing" and the content parts from "content", building a CargoSupplier object which has both bits.
Is that what you were after?

Use Enumerable.Concat:
Concatenates two sequences.
Example:
var result = cargoSuppliers_Content.Concat(cargoSuppliers_Pricing);

Seen the Union() extension method? That should do what your after
IEnumerable<CargoSupplier> allCargoSuppliers = cargoSuppliers_Pricing.Union(cargoSuppliers_Content);

Related

Entity Framework Core - optional foreign key

I am creating a web api that needs to return details about vehicles. The first part works fine, just returning data from my vehicles table. Now I have another table which may or may not contain additional data about vehicles in the first table. So when I get vehicle data, I want all of the vehicle data, and any additional data from the second table if it exists, like a left join in SQL.
Here are my classes (very much abridged for readability):
public class Vehicle
{
[Key]
[Required]
public string registrationNo { get; set; }
public string capacity{ get; set; }
public string maxGross{ get; set; }
}
public class VehicleDvlaDetail
{
[ForeignKey("Vehicle")]
public string? registrationNumber { get; set; }
public int? co2Emissions { get; set; }
}
And in my context class OnModelCreating I have (again, very abridged):
modelBuilder.Entity<Vehicle>(entity =>
{
entity.HasOne(dvlaRec => dvlaRec.dvlaDetail).WithMany().HasForeignKey(dvla => dvla.registrationNo);
});
This works fine when there is an associated record in the DVLA table, but that isn't always the case. I need to keep them as separate entities as my API will be required to return details from the DVLA table separately as well. Is there any way to create an optional foreign key, as clearly, what I am doing is wrong.
Friendly advice:
Primary key as a string is not a good practice because of performance issues when data table has lots of data in it.
It would be better if you create your model like this:
public class Vehicle
{
public long Id { get; set; }
public string RegistrationNo { get; set; }
public string Capacity { get; set; }
public string MaxGross { get; set; }
public List<VehicleDvlaDetail> VehicleDvlaDetails { get; set; }
}
public class VehicleDvlaDetail
{
public long? VehicleId { get; set; }
public int? Co2Emissions { get; set; }
public Vehicle Vehicle { get; set; }
}
Vehicle and VehicleDvlaDetail are now connected without additional code in OnModelCreating method and it is possible to fetch vehicles with details like this (this is assuming you have named properties in dbcontext Vehicles and VehicleDvlaDetails):
_dbContext.Vehicles.Include(x => x.VehicleDvlaDetails).ToList();
Also as foreign key VehicleId is nullable - this allows for vehicles not to have any dvla details.
Wow. I spent about 3 hours looking for the answer, just posted the question and came across this:
Create an optional foreign key using the fluid-API for Entity Framework 7
So simple...

Circular Reference with Include in .NET Core

I am using code like below in .NET core
.Include(p => p.Company).ThenInclude(p => p.Country).ToList();
My classes look like below,
public partial class Company
{
public Guid Id { get; set; }
public string Name { get; set; }
public virtual Country Country { get; set; }
}
public partial class Country
{
public Country()
{
Companies = new HashSet<Company>();
}
public Guid Id { get; set; }
public string Name { get; set; }
public string ShortCode { get; set; }
public virtual ICollection<Company> Companies { get; set; }
}
And I want only Company and then Country in side the company to be populated. But I am getting the Company inside the Country and then Country in those Companies and so on populated which is causing the response delayed.
I have already tried difference examples of Include on Google/StackOverFlow.
This isn't actually a problem. EF has what's called "object fix-up". Internally, it uses an object cache. When it builds entity instances for database query results, it adds those to the object cache, allowing it to then pull out those objects later, rather than issuing the same queries again.
Because of this object cache, if it already existing entity instances corresponding to a relationship, it will auto-fill that relationship from the object cache. It's not issuing a series of circular queries forever.

Display results from multiple sources in ASP.NET

Okay, so I'm in the middle of an ASP.NET project in work at the minute and it's all going well. So far I have all the models, views and controllers made and they all work perfectly, but now I have been told that I need to make a class (lets just call it results to make life easy here) to display all the data. This is an example I was given for what the displayed results would look like:
There are multiple different displays at the moment for different things like a person, travel insurance, car insurance etc. and the only common things between each different display are the full name, contact email, contact number, contact address and recorded time stamp. It's the additional data that changes for each display depending on what is being requested, i.e., person displays all the information stored about the person like full name, age, DOB, mobile number, home address and so on while travel insurance displays all information stored about the travel insurance for the person who is asking like the trip type, trip destination, group type (single/couple/family/friends), travelers ages and so on..
My question is this: how do I create this results class to display the required data? Do I need another controller, model and view or do I just need to create a class called Result and put everything into that? (I think I just have to create a class but I am not sure, hence why I am asking) Also, how do I make it in such a way that different things are displayed in the additional data depending on what the person searched for? Like I don't need all the additional data about car insurance appearing when a person searched their travel insurance - does this mean I will need multiple forms of the results class which all refer to a different searchable thing or can everything go in the one class?
Apologies if this is awfully worded and/or a bad question - I did try looking for something to help myself before posting here but I couldn't find anything. I'm also quite new to the whole ASP.NET front so apologies if I'm missing anything obvious.
Create a base Model class and put all the common properties to be displayed in that, and derive other Model classes from that class with their specific properties in them. You can pass Person object to the view where Person's info need to be displayed and TravelInsurance object where Travel Insurance's info needs to be displayed.
public class ModelBase
{
public string FullName { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Address { get; set; }
public DateTime TimeStamp { get; set; }
}
public class Person : ModelBase
{
public string DateOfBirth { get; set; }
public string MobileNumber { get; set; }
}
public class TravelInsurance : ModelBase
{
public string TripType { get; set; }
public string TripDestination { get; set; }
}
If that does not sound like the way to go, you can have a generic Model class with a generic Data property within it:
public class Model<T>
{
public string FullName { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Address { get; set; }
public DateTime TimeStamp { get; set; }
public T Data { get; set; }
}
public class Person
{
public string DateOfBirth { get; set; }
public string MobileNumber { get; set; }
}
public class TravelInsurance
{
public string TripType { get; set; }
public string TripDestination { get; set; }
}
where you can pass objects to your view like this:
var x = new Model<Person> { FullName = "...", Data = new Person { } };
OR
var x = new Model<TravelInsurance> { FullName = "...", Data = new TravelInsurance { } };

Is ok to add [BsonAttribute] to POCOs?

I have an application, structured like this:
Application.Domain
Application.Web.Mvc
Application.MongoDb
In Application.Domain i keep all the POCOs of the application (the domain models).
public class Product
{
public string Id { get; set; }
public string ProductName { get; set; }
public DateTime CreatedDate { get; set; }
}
Now, because i am using MongoDb, i also need to use some of the [BsonAttribute], in order to customize the serialization process.
For example:
public class Product
{
[BsonId]
public string Id { get; set; }
public string ProductName { get; set; }
[BsonDateTimeOptions(Kind = DateTimeKind.Local, DateOnly = true)]
public DateTime CreatedDate { get; set; }
}
If i add these attributes, i will need to also add a reference to MongoDB.Bson.Serialization.Attributes in the Application.Domain project, which i want to avoid.
I think the correct way to do this is to create mapping objects in the Application.MongoDb project, and always map them from POCO to MongoObjects and the other way around every time i work with MongoDb repos.
If this is the correct solution, isn't this a bit overkill?

Is it OK to declare a DBSet in the context for both a base table and a derived table?

I have a SalesOrder table which inherits from a SalesDocument table using Table Per Type Inheritance
The ( simplified) table classes are;
[Table("SalesDocumentHeaders")]
public abstract class SalesDocumentHeader
{
[ForeignKey("CreatedByUserId")]
public virtual User CreatedBy { get; set; }
[Required]
public int CreatedByUserId { get; set; }
[Required]
public virtual DateTime? DocumentDate { get; set; }
[Required]
public String ReferenceNumber { get; set; }
}
[Table("SalesOrders")]
public class SalesOrder : SalesDocumentHeader
{
[Required]
public String CustomerOrderNumber { get; set; }
public DateTime? DeliverBy { get; set; }
public virtual SortableBindingList<SalesOrderLine> Lines { get; set; }
}
The context contains
public DbSet<SalesOrder> SalesOrders { get; set; }
public DbSet<SalesDocumentHeader> SalesDocumentHeaders { get; set; }
It doesn't strictly need the SalesOrders DBSet, since SalesOrder inherits from SalesDocumentHeader however I find it convenient.
It seems to work OK, but I am worried that there are 2 ways of reaching the same record , am I doing something wrong?
Usually you only need to keep the DBSet for the base table. This helps when you have multiple derived tables (call them A and B) and you need to decide the actual type dynamically.
For example if you have another entity which references type A or B (like a user can have different types of contact information), you can reference the base table and EF will resolve the correct concrete type at runtime. Though of course this adds some extra casting code.

Resources