Get list item where sublist can be null - entity-framework

Hi I have a situation where I have a Car, and Car has many customizations and customizations possibly have many versions.
I am trying to get the car customization if it has a version that versionName contains "xyz".
var customizationToBeUpdated = car.Customizations.FirstOrDefault(pv =>
pv.Versions.Any(ver =>
ver.Name.Contains("xyz")));
This code above works when it finds a version that matches, but if it doesn't find throws an exception. Any suggestion on how to deal in the case is null?
Exception: System.NullReferenceException: Object reference not set to an instance of an object.
Cheers

A null safe code would be using the null conditional (?.) operator with the null coalescing (??) operator.
Something like this:
var customizationToBeUpdated = car.Customizations.FirstOrDefault(pv =>
pv.Versions?.Any(ver =>
ver.Name?.Contains("xyz") ?? false) ?? false);
Basically, pv.Versions?.Any will only execute Any if Versions is not null, but if it is null, it will simply return null, same as Name?.Contains will only execute Contains is Name is not null - hence the usage of the ?? false in both conditions.

Requirement
You wrote:
I am trying to get the car customization if it has a version that versionName contains "xyz".
"The" car Customization? Does the car have exactly one Customization with this VersionName?
Car A has three Customizations: K, L, M
K has one Version: "1.0"
L has two Versions: "1.0" and "2.0"
M has three Versions: "1.0" "1.1" "2.0"
Give me "the" Customization of Car A that has a version "1.0".
Classes
Alas you forgot to give us your classes. If you've followed the entity framework code first conventions you'll have classes like this:
class Car
{
public int Id {get; set;}
... // other properties
// Every Car has zero or more Customizations (one-to-many)
public virtual ICollection<Customization> Customizations {get; set;}
}
class Customization
{
public int Id {get; set;}
... // other properties
// Every Customization belongs to exactly one Car, using foreign key
public int CarId {get; set;}
public virtual Car Car {get; set;}
// Every Customization has zero or more Versions (one-to-many)
public virtual ICollection<Version> Versions {get; set;}
}
class Version
{
public int Id {get; set;}
public string Name {get; set;}
... // other properties
// Every Version belongs to exactly one Customization, using foreign key
public int CustomizationId {get; set;}
public virtual Customization Customization {get; set;}
}
This is all that entity framework needs to detect the one-to-many relations.
In entity framework the columns of the tables are represented using non-virtual properties; the virtual properties represent the relations between the tables (one-to-many, many-to-many, ...)
Hence a foreign key is non-virtual; the object that the foreign key refers to is virtual.
Back to your question
Requirement: Given a car and a versionName, give me all Customizations of this Car that has at least one Version with a Name equal to this VersionName
Car car = ...
string versionName = ...
You can start at Customizations or at Versions:
Start at Customizations: Give me the Customizations of my Car that has at least one Version with a Name equal to versionName:
var result = dbContext.Customizations
.Where(customization =>
// it is one of the customization of my car:
customization.CarId == car.Id
// and this customization has at least one Version with versionName:
customization.Versions.Where(version => version.Name == versionName))
.Any());
You can also start at Versions:
From every Version that has a Name equal to versionName and a Customization of my car, give me some properties of the Customization:
var result = dbContext.Versions
// keep only the Versions that have the correct VersionName
// and that is a Customization of my car:
.Where(version => version.Name == versionName
&& version.Customization.CarId == car.Id)
// from the remaining Versions Select the properties that you plan to use
.Select(version => new
{
// Select the Customization properties that you want:
Id = version.Customization.Id,
CustomizationCode = version.Customization.Code,
...
});

Related

EF Core 3.0 1:0 relationship with fluent

EF Core 3.0... I can't find a precise answer for this completely normal mapping.
Principal to Dependent with no back pointer to Principal, 1:0 relationship, a Type Object / Lookup table set up. The problem is that the Object Key Name "RunId" is different than the EFCore generated key name "ServiceRunId"
How can I use Fluent API to replace the [ForeignKey("aServiceRun")] annotation?
This is my current Fluent set up, but I don't know where to put the ForeignKey mapping.
aBuilder.Entity<ServiceRun>().HasKey(new string[] { "RunId "});
aBuilder.Entity<Service>().HasOne(s => s.aServiceRun);
Class Service {
public int ServiceId {get; set;}
[ForeignKey("aServiceRun")]
public int RunId { get; set; }
public virtual ServiceRun aServiceRun { get; set; }
}
Class ServiceRun {
public int RunId { get; set; }
public string description {get ;set; }
}
Tables:
Service {
ServiceId int
RunId int
}
SerivceRun {
RunId int
Description string
}
How can I use Fluent API to replace the [ForeignKey("aServiceRun")] annotation?
You are seeking for HasForeignKey fluent API. But in order to get access to it (and other relationship configuration APIs), you need to define the relationship by using Has{One|Many} followed by With{One|Many}. For one-to-one relationships you also need to provide the generic type argument to HasForeignKey:
When configuring the relationship with the Fluent API, you use the HasOne and WithOne methods.
When configuring the foreign key you need to specify the dependent entity type - notice the generic parameter provided to HasForeignKey in the listing below. In a one-to-many relationship it is clear that the entity with the reference navigation is the dependent and the one with the collection is the principal. But this is not so in a one-to-one relationship - hence the need to explicitly define it.
Note that the entity containing the FK is always the dependent, so with your model the ServiceRun is the principal, Service is the dependent, and the fluent configuration is a follows:
modelBuilder.Entity<Service>()
.HasOne(s => s.aServiceRun) // navigation property
.WithOne() // no navigation property
.HasForeignKey<Service>(s => s.RunId); // foreign key
I found my answer to the above problem - I had a back-pointing list on my ServiceRun object that was not configured or ignored. I decided to leave this here as another example. Perhaps it will provide some worth to someone.
This is a 1:0 from Service to ServiceRunType where table names and property/field names don't match perfectly.
Tables
ServiceRun { //Does not match object name
int Id,
string Desc
}
Service {
int Id,
int RunId //Does not match object
}
Objects
Class ServiceRunType{ //Does not match table name
public int Id {get; set;}
public String Desc {get; set;}
}
Class Service{
public int Id {get; set;}
public int RunTypeId {get; set;} //Does not match table
public virtual ServiceRunType aServiceRunType { get; set; }
}
Fluent Code
modelBuilder.Entity<ServiceRunType>()
.ToTable("ServiceRun", schema: "load")
.HasKey(new string[] { "Id" });
modelBuilder.Entity<Service>()
.ToTable("Service", schema: "load") //Had to specify schema
.HasKey(new string[] { "Id" });
modelBuilder.Entity<Service>()
.Property("RunTypeId")
.HasColumnName("RunId");
modelBuilder.Entity<Service>()
.HasOne(s => s.aServiceRunType)
.WithOne()
.HasForeignKey<Service>(s => s.RunTypeId);

What is the best practice regarding setting Id's of contained entities in entity framework core

Assuming i have the following entities that i store in a database using entity framework core
public class Container{
public int ContainerId {get; set;}
public int ContainedId {get; set;}
public Contained Contained {get; set;}
}
public class Contained {
public int ContainedId {get; set;}
public int ValueA {get; set;}
public int ValueB {get; set;}
}
if at some point in time i decide to save a Container class, with a know Contained class should i manually set the Id?
var containerToSave = new Container{
Contained = contained;
ContainedId = contained.ContainedId
}
or this is a bad practice? If I set it with an id that doesnt match the one in the actual class what will it save?
As far as Entity Framework goes you can specify either a foreign key or add the related entity when saving the main one.
To answer your question... No, is not a bad practice and this isn't related to the EF either. Rather your Container matches the Contained is a business related problem and should be treated and validated there. EF role in your case is to save the data whatever method you choose.
Assuming you mark the Contained EF will give you 2 choices:
public virtual Contained Contained { get; set; }
Add the foreign key:
var containerToSave = new Container
{
ContainedId = contained.ContainedId
}
Add the entity itself:
var containerToSave = new Container
{
Contained = new Contained
{
ValueA = x;
ValueB = y;
}
}
In you case, if you already have the Contained added, you can go with the first one but not the less, either of above methods are working just fine.

Table with with different fields depending on category

I have table that has these columns:
Id
Title
Description
CreateDateTime
CategoryId
Picture
quantity
Price
RentPrice
WantToExchange
NumberOfRoom
DepositPrice
Only the first 6 are required for each row and other column will be null based on entity category.
For example in cat1 only first 6 field and Price filled by user,and in cat2 only first 6 field and RentPrice, DepositPrice are filled, so after a while many column of table rows become a null
I see some solution in NopCommerce source code that used for store various product property in different language - there are entity called LocalizedProperty and storeEntityId, LanguageId, Name of entity, name of field and its value
it use
Expression<Func<T, TPropType>>
and PropertyInfo to get name of field, but I am searching for an easier way.
How can I redesign my entity?
If you'd have designed this object orientedly, you would probably have create a PictureDescription class, and a PicturePrice class, that would have the other properties.
Every PictureDescription would have zero or one PicturePrice object: a straightforward aggregation
If you want zero-or-one in a relational Database, then this is quite often done using two tables, with a foreign key from one table pointing to the other table.
See Entity Framework zero-or-one-to-one
class PictureDescription
{
public int Id {get; set;}
public string Title {get; set;}
...
// every PictureDescription has zero or one PicturePrice
public virtual PicturePrice PicturePrice {get; set;}
}
class PicturePrice
{
public int Id {get; set;}
public decimal Price {get; set;}
...
// every PicturePrice belongs to exactly one Picture, using foreign key
public int PictureDescriptionId {get; set;}
public virtual PictureDescription PictureDescription {get; set;}
}
This will be enough for entity framework to detect your columns and the relations between the tables. If you want to use fluent API, in DbContext.OnModelCreating:
// every PictureDescription has zero or one PicturePrice:
modelBuilder.Entity<PictureDescription>()
.HasOptional(description => description.PicturePrice)
.WithRequired(price => price.PictureDescription)
.HasForeignKey(price => price.PictureDescriptionId);

Entity Framework Code First Foreign Key Problems

I am trying to use EF Code First on an existing database. I first tried some of the reverse-engineering tools, but I ran into problems with that, so at the moment I am trying to hand-code some of the classes. I am having some trouble getting some of the foreign key relationships set up. Consider two tables. The first is called LocaleValueLookup:
public class LocaleValueLookup
{
public int Id { get; set; }
public Guid Guid { get; set; }
}
This table provides an Id for multi-language text held in a different table (that other table is not important for the purposes of this question). The second table is called SectionType, and it has an optional FK to LocaleValueLookup:
public class SectionType
{
public int EnumId { get; set; }
public string Name { get; set; }
public int? DefaultSectionTextLocaleValueLookupId { get; set; }
// Navigation property
public LocaleValueLookup DefaultSectionTextLocaleValueLookup { get; set; }
}
I have tried various things, including adding a [ForeignKey] attribute to the SectionType.LocaleValueLookup property, and various incantations in the DbContext.OnModelCreating() override, but when I query the DbContext, I can't get the DefaultSectionTextLocaleValueLookup to be anything but null. I can retrieve other objects from the context just fine, and I have verified that DefaultSectionTextLocaleValueLookupId is not null at least some of the time.
My OnModelBuilding() contains the following:
modelBuilder.Entity<LocaleValueLookup>()
.ToTable("LocaleValueLookup")
.HasKey(lvl => lvl.Id);
modelBuilder.Entity<LocaleValueLookup>().Property(lvl => lvl.Id).IsRequired();
modelBuilder.Entity<SectionType>()
.ToTable("SectionType")
.HasKey(st => st.EnumId);
modelBuilder.Entity<SectionType>().Property(st => st.EnumId).IsRequired();
A couple of other points:
I would prefer not to have a SectionType collection on the LocaleValueLookup object. LocaleValueLookup is a low-level class that a lot of other classes depend on, so to include a collection property on LocaleValueLookup for every other class that references it will make for an unwieldy class with a lot of collections on it that I don't need from a domain perspective.
I would prefer to do the mapping setup in DbContext.OnModelCreating() rather than using attributes on my model objects
Any help would be greatly appreciated!
It looks like your foreign key is nullable so that means an optional -> many relationship.
Could you try something like this:
modelBuilder.Entity<SectionType>()
.HasOptional(opt => opt.DefaultSectionTextLocaleValueLookup)
.WithMany() // no navigation on the other side
.HasForeignKey(fk => fk.DefaultSectionTextLocaleValueLookupId);
If you were to write a query like this you should get a value back:
var query =
from st in db.SectionTypes
where st.EnumId == 12345
select new
{
SectionType = st,
LocaleValue = st.DefaultSectionTextLocaleValueLookup
};
It will only be non-null if the foreign key has a value, obviously.

Code First: Independent associations vs. Foreign key associations?

I have a mental debate with myself every time I start working on a new project and I am designing my POCOs. I have seen many tutorials/code samples that seem to favor foreign key associations:
Foreign key association
public class Order
{
public int ID { get; set; }
public int CustomerID { get; set; } // <-- Customer ID
...
}
As opposed to independent associations:
Independent association
public class Order
{
public int ID { get; set; }
public Customer Customer { get; set; } // <-- Customer object
...
}
I have worked with NHibernate in the past, and used independent associations, which not only feel more OO, but also (with lazy loading) have the advantage of giving me access to the whole Customer object, instead of just its ID. This allows me to, for example, retrieve an Order instance and then do Order.Customer.FirstName without having to do a join explicitly, which is extremely convenient.
So to recap, my questions are:
Are there any significant disadvantages in
using independent associations? and...
If there aren't any, what
would be the reason of using foreign key associations at all?
If you want to take full advantage of ORM you will definitely use Entity reference:
public class Order
{
public int ID { get; set; }
public Customer Customer { get; set; } // <-- Customer object
...
}
Once you generate an entity model from a database with FKs it will always generate entity references. If you don't want to use them you must manually modify the EDMX file and add properties representing FKs. At least this was the case in Entity Framework v1 where only Independent associations were allowed.
Entity framework v4 offers a new type of association called Foreign key association. The most obvious difference between the independent and the foreign key association is in Order class:
public class Order
{
public int ID { get; set; }
public int CustomerId { get; set; } // <-- Customer ID
public Customer Customer { get; set; } // <-- Customer object
...
}
As you can see you have both FK property and entity reference. There are more differences between two types of associations:
Independent association
It is represented as separate object in ObjectStateManager. It has its own EntityState!
When building association you always need entitites from both ends of association
This association is mapped in the same way as entity.
Foreign key association
It is not represented as separate object in ObjectStateManager. Due to that you must follow some special rules.
When building association you don't need both ends of association. It is enough to have child entity and PK of parent entity but PK value must be unique. So when using foreign keys association you must also assign temporary unique IDs to newly generated entities used in relations.
This association is not mapped but instead it defines referential constraints.
If you want to use foreign key association you must tick Include foreign key columns in the model in Entity Data Model Wizard.
Edit:
I found that the difference between these two types of associations is not very well known so I wrote a short article covering this with more details and my own opinion about this.
Use both. And make your entity references virtual to allow for lazy loading. Like this:
public class Order
{
public int ID { get; set; }
public int CustomerID { get; set; }
public virtual Customer Customer { get; set; } // <-- Customer object
...
}
This saves on unnecessary DB lookups, allows lazy loading, and allows you to easily see/set the ID if you know what you want it to be. Note that having both does not change your table structure in any way.
Independent association doesn't work well with AddOrUpdate that is usually used in Seed method. When the reference is an existing item, it will be re-inserted.
// Existing customer.
var customer = new Customer { Id = 1, Name = "edit name" };
db.Set<Customer>().AddOrUpdate(customer);
// New order.
var order = new Order { Id = 1, Customer = customer };
db.Set<Order>().AddOrUpdate(order);
The result is existing customer will be re-inserted and new (re-inserted) customer will be associated with new order.
Unless we use the foreign key association and assign the id.
// Existing customer.
var customer = new Customer { Id = 1, Name = "edit name" };
db.Set<Customer>().AddOrUpdate(customer);
// New order.
var order = new Order { Id = 1, CustomerId = customer.Id };
db.Set<Order>().AddOrUpdate(order);
We have the expected behavior, existing customer will be associated with new order.
I favour the object approach to avoid unnecessary lookups. The property objects can be just as easily populated when you call your factory method to build the whole entity (using simple callback code for nested entities). There are no disadvantages that I can see except for memory usage (but you would cache your objects right?). So, all you are doing is substituting the stack for the heap and making a performance gain from not performing lookups. I hope this makes sense.