Circular Reference with Include in .NET Core - .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.

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...

MongoDB basic (Relation between two objects)

I am totally new in mongoDB.
I have two objects :
public class BusinessUnit{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
public string Name { get; set; } = string.Empty;
public string Address{ get; set; } = string.Empty;
}
public class Review
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
public decimal Rating { get; set; } = 0;
public BusinessUnit BusinessUnit { get; set; }
}
N.B : Please ignore other properties in given images.
I have a business unit and want to save a review document with that business unit.
I save it successfully. But I am facing a problem.
My problem is after saving a BusinessUnit and review (with that business unit) when I update my BusinessUnit's Name it is unchanged in review document.
I want to know why it's happened.
Am I missing something?
Below is my documents.
Thanks in advance.
MongoDB does not work like Relational databases. So if it is updating in one collection, it wont affect other collection data. No idea where ASP.net internally handles the updation process. Otherwise you need to rethink about your design.

ASP.NET - Editable form at runtime + storing info about it in database/SQL session state

I was wondering whether someone has another sources of info about modifiable forms at runtime + how to store them.
What I have:
I have 3 tables atm:
Users (1 to many) Raports (1 to many) ThrashType
Raport class:
public class Raport
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Raport()
{
ThrashType = new HashSet<ThrashType>();
//Raport = new HashSet<Raport>();
}
[Key]
public int raport_id { get; set; }
public string who_did { get; set; }
public string where_from { get; set; }
public DateTime creation_time { get; set; }
public DateTime last_modyfication { get; set; }
public virtual ICollection<ThrashType> ThrashType { get; set; }
public virtual AspNetUsers AspNetUsers { get; set; }
}
ThrashType class:
public class ThrashType
{
[Key]
public int Key { get; set; }
//public string Name { get; set; }
//or type from dictionary that has around 100 words
public int Quantity { get; set; }
//public string CreatorsName { get; set; }
public virtual Raport Raport { get; set; }
}
What I want:
create a form that user can modify (meaning appending another instances of ThrashType to a Raport which in turn will be assigned to certain User)
recreate form made by user from stored record (also with information about name, quantities and so on)
learn more about storing serialized data or mb inspiration for the database
get more articles or information sources that could provide help
What I've read:
http://www.codeproject.com/Articles/32545/Exploring-Session-in-ASP-Net#26
http://adventuresdotnet.blogspot.com/2009/06/aspnet-moving-session-out-of-process.html
ASP.NET MVC - Adding form elements at runtime with javascript
and many more but wish not to spam this place
What I don't know:
how to append next instances of ThrashType to Raport at runtime
after having the custom Raport (that has 1-many ThrashTypes) how to
store it:
(by how I mean "which way would be best")
a) in database (it will later be analized by a set of
queries I'll invent based on what client will say)
b) how to
store it in SQL session state
What I wanted to do:
At first I thought that I could store information from form as a string that could be read from alghoritm later (like "10101011101" and position would say what kind of word from dictionary it is), but still it lacks the quantities. Querying string database for quantities seems like overkill-crazy idea. I'm thinking about mixing session and database - session for recreation of dropped work and database for storing ready reports that could be analized. Anyway I need your opinion and inspiration because it's killing me softly.
Even an answer to 1 part of this problem would be of very much needed and appriecieted help.
Thanks!

Unable to establish One to Many Relations in MVC 6 Views

As a learning exercise, I was trying to form a simple One to many Relation between Vendors and Shops where each Vendor has multiple shops.
Using two model classes I achieved the following:
This is what scaffolding gives me for Shops
Why am I not getting a drop down here?
Not sharing any code as of now. As most of it is auto generated. Let me know if someone would like me to paste the code for my models.
Another doubt why are my table Columns alphabetically Ordered? If I am not mistaking entity framework 6 used to order it as per the class definition. Is there a way to override it? Cause the view scaffold seems to mirror the DB in terms of ordering objects.
Thanks.
Update:
I added a property Vendorid in the Shops Class. Now I see the Dropdown but no values. Do I need to get down to Fluent API for achieving this?
public class Shops
{
public int Id { get; set; }
public String Name { get; set; }
public int Rank { get; set; }
public String Address { get; set; }
public Boolean Active { get; set; }
public int VendorId { get; set; }
public Vendors Vendor { get; set; }
}
Vendors
public class Vendors
{
public int Id { get; set; }
public String Name { get; set; }
public int Rank { get; set; }
public Boolean Active { get; set; }
public ICollection<Shops> Shops { get; set; }
}
Env: Visual Studio 2015 (Latest ASP.net Patch Applied).
Project Template: Web Application
This depends on what approach on EF you are using. Are you sure they have relationship in their classes? If your using code first, you have to map it manually using fluent API. on OnModelCreating method on DbContext class, use something like this
modelBuilder.Entity().HasMany(v => v.Shop).WithOptional(s => s.Vendor).
If your using Database First, just create relationship on tables diagram(or script) and update the model on your project and EF will create it for you.

Consolidate/Merge data from TWO IEnumerable Lists into ONE

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);

Resources