Entity framework inheritance - entity-framework

I'll try to explain the problem I'm currently facing as simply as possible.
The project I'm currently working on is required to analyze some financial data. For convenience, this data should be stored in a database, so I'm tasked with creating a database model. While the database wasn't required up until now, the application itself has been developed for a number of years and already has all the data types and classes defined, so my task is to match the database model to the classes used by application. Here's a simplified breakdown of a class composition used by application to work with the data.
To start with, there's an abstract Entry class that all other financial data entries are inherited from:
abstract class Entry
{
public Guid ID { get; set; }
public string Name { get; set; }
}
Different financial data comes in different formats an is relevant to different points in time. To reflect this, there's a number of interfaces that are implemented by concrete data types. As an example, lets say that all the data can either be relative to a certain point in time or a period in time. Take currency rate for example. It only changes once a day. GDP, on the other hand, is usually provided for a certain period (either quarterly or yearly). This is reflected by the classes provided below.
class SingleDateEntry : Entry
{
public DateTime Date { get; set; }
}
class PeriodEntry : Entry
{
public DateTime PeriodStart { get; set; }
public DateTime PeriodEnd { get; set; }
}
Furthermore, the data can be represented in different formats. Some data only has a single value, like the currency rate for example, other data can come in data sets, like daily stock prices, which have an opening and closing daily prices, as well as maximum and minimum daily prices.
interface ISingleValueEntry
{
public double Value { get; set; }
}
interface IMinMaxEntry
{
public double MinPrice { get; set; }
public double MaxPrice { get; set; }
}
interface IOpenCloseEntry
{
public double OpenPrice{get;set;}
public double ClosePrice{get;set;}
}
As an example, the daily currency rate, since it is associated with a single day in the past and only has one value, could be represented by a class that looks like this:
class DailyCurrencyRate : SingleDateEntry, ISingleValueEntry
{
}
The stock prices have a number of different values associated with them, so they can be represented like this:
class DailyStockPrice : SingleDateEntry, IOpenCloseEntry, IMinMaxEntry
{
}
And finally, GDP, since it is associated with a period in time and has a single value, would look like this:
class GDP : PeriodEntry, ISingleValueEntry
{
}
Unfortunately, I haven't worked with EF before, and when I tried to implement this simplified scenario of the actual problem I've run into a number of problems, so I would appreciate any suggestions that could help me out resolving them.
To start with, how to deal with multiple interface implementations? As far as I know EF doesn't support multiple inheritance, and by using associations, I don't get classes that implement them, rather it generates classes that contain references to objects that implement these interfaces, which is bad, since it doesn't matches the interface expected by the application. Furthermore, what type of inheritance should be used it this scenario? From what I understood after my research, TPC would be a better strategy, but I might be wrong about that.
Thanks in advance for any pointers, suggestions and "gotchas".

Multiple inheritance is not provided by .NET framework and you don't use multiple inheritance. Each your class inherits only from single parent class. I just tested simple scenario with Code first approach (not part of EF4.0). I modeled three classes in A, B inherited from A and C inherited from B. I stored C as TPH (TPH for code first) without any problems. It will also work with common EF approach.

Related

EF Core deserialization of a database item into various types

I have a range of entities which have a series of common properties being a informationItem and a series of specific entity properties which I intend to store as JSON property Detail in SQL Server; e.g.
public class InformationItem
{
public Guid InformationItemId { get; set; }
public InformationItemType Type { get; set; }
public string Detail { get; set; }
}
InformationItemType is from an enum with a collection of project elements such as Assumptions, benefits, constraints, tasks etc.. There are some 20 object types which specific specific Detail properties.
I don't want to have 20+ entity specific tables in the database but what I would like to do is 'inflate' them into their real concrete classes of Assumption, Benefit, Constraint, Task etc deserializing the JSON Detail into the specific properties of the type when entity framework does its 'magic'.
the main reason I am after this is that each entity will have lost of many to many relationships associated with them such as their relationship to a user etc and I don't wat the user to end up with multiple virtual ICollections of the various types.
Is it possible to store InformationItems with a specific type identifier and Detail JSON information in the database and have EFCore return these as their concrete class types?

EF Code-First Design: Common Collection Type on different parent types/tables

I need help with a design question using Entity Framework 6.1.3 from a Code-First perspective.
We have tables called "Businesses", "People", and "PhoneNumbers". A business can have one-to-many phone numbers and person can have one-to-many phone numbers. I'm struggling to determine the best way to implement this. The following solutions have been explored but neither strikes me as being the "obvious" solution. Can you please offer advice?
Use a common Phone table to hold numbers for the Business and People.
In this solution, the Phone table would have RI to the People table and to the Business table. The ID fields would be nullable so that when it is a business phone, the participant ID would be null and vice-versa:
public Nullable<int> ParticipantID { get; set; }
public Participant Participant { get; set; }
public Nullable<int> BusinessID { get; set; }
public Business Business { get; set; }
Create separate tables for the Business (BusinessPhone) and Person (PersonPhone) phone numbers. Both phone tables could inherit from the original phone table but each would have separate RI statements to the corresponding Business or Person. This way, neither table would need a nullable key.
For example, the PersonPhone table would look something like:
public class PersonPhone : Phone
{
public int ParticipantID{ get; set; }
public Participant Participant { get; set; }
}
Are either of these solutions best practice? Is there a better solution? What do you recommend?
I will suggest that the best option is to use separate tables for this. Use a common ABC called PhoneNumber, and derive subclasses for each collection parent type, each mapped to their own table (TPC strategy). Or, map the ABC to a common table for the common fields, and referenced tables for the references to Person or Business (TPT strategy).
Coming from an object-oriented background where we often optimize for code-reuse; with inheritance being a strategy for reusing code; and with TPH being the default mapping of inheritance structures in EF; it feels right to have these both in a single table. But looking from the perspective of a DBA, mashing these two concerns together is an abuse of the data structures in the database. Call it "schema-smell". It might work, but you are giving up a lot of what the database can do for you. You're painting yourself into a corner for no good reason.
There are three inheritance strategies; this EF tutorial site has a good rundown. The single-table is TPH. Usually I will use this even though it violates 3rd normal form, because it is simple and performant. In the case where types differ by the other types they reference, though, the denormalization compromises offer diminishing returns.
The main problem as I see it: With one table, you have to figure out a way to mash separate FKs in. With one column and a discriminator (which may not even be legal with EF) you lose the ability to do DRI and cascading deletes. With two columns, you'll have to monitor that one and only one is non-null at any given time. With either solution, you'll be giving up storage space. If the two objects ever diverge--say, you have to add an EmployeeName to BusinessPhone--the problem will only be exacerbated.
So, in this case I would recommend either the table-per-type or table-per-concrete-type strategy over table-per-hierarchy.
The only remaining note is that all three involve compromises. I won't get into all the trade-offs (you should be able to find many discussions of these). There may still be cases where TPH makes the most sense because of a use-case that must perform very well.
I think the best way to go at it is to have a table named 'PhoneNumber'. Both Business and People can have a list of PhoneNumbers.
Ofcourse this is only true if the PhoneNumber is equal for both Business and People. If you would like to add extra properties to a PhoneNumber for People, I would suggest going with your second option.
Having a single table for phone numbers seems like the better option. Could you use some sort of discriminator on your PhoneNumbers entity to avoid having to have two nullable columns?
So you'd have a PhoneNumber class, and an enumerable representing the phone number type. Then your Businesses and People each have a list of PhoneNumber as you've mentioned. Example -
public class PhoneNumber
{
public int PhoneNumberId { get; set; }
public int PhoneNumber { get; set; }
public PhoneNumberType PhoneNumberType { get; set; }
public Participant Participant { get; set; }
}
public enum PhoneNumberType
{
Person,
Business
}
This answer is to a very similar question and seems like an even better option if you want to give it a look.

add several references to the same record in navigation property

In my EF 6 Model First application, I have an entity with a many-to-many navigation property to another entity. In the first entity, I need to add several references to the same record in navigation property.
The first entity is a “saleslistItem” and the second entity is “warehouseItem”. Normally there will be a one-to-one relationship here, but exceptionally there will be some bundles where one “saleslistItem” contains several “warehouseItems”. “WarehouseItem” can also be included in several “salesListItems”. At the end of the project, my customer says, testing it, that “saleslistItem” must be able to consist of several “WarehouseItems” of the same kind (like two boxes of smoked ham).
These data is used several places in my code. (ie. doing a sale removes items from the warehouse) If I could just add several the same reference, my code would work without any modifications. But in the implementation of the navigation property the “hashtable”-collection is used, and this collection requires unique entries. Is there a workaround here? Performance is irrelevant as the data amount is small.
If there are no such workaround, is it possible to store values together with the instance of navigation property? Maybe it is implemented as a field in the join-table???
Any other suggestions?
Need a solution so the customer pays the last part of the bill!
So you currently have a 1:1 from SalesListItem toWarehouseItemvia a ForeignKey inSalesListItem`? Sounds like you need:
public class SalesListItem
{
public virutal ICollection<SalesListWarehouseItem> WareHouseItems { get; set; }
}
public class SalesListWarehouseItem
{
public virtual SalesListItem Parent{ get; set; }
public virtual WarehouseItem WarehouseItem { get; set; }
public int Quantity { get; set; } // maybe double?
}

How to prevent cyclic loading of related entities in Entity Framework Code First

I'm new to Entity Framework and am trying to learn how to use Code First to load entities from the database.
My model contains a user:
public class User
{
public int UserID { get; set; }
[Required]
public string Name { get; set; }
// Navigation Properties
public virtual ICollection<AuditEntry> AuditEntries { get; set; }
}
Each user can have a set of audit entries each of which contains a simple message:
public class AuditEntry
{
public int AuditEntryID { get; set; }
[Required]
public string Message { get; set; }
// Navigation Properties
public int UserID { get; set; }
public virtual User User { get; set; }
}
I have a DBContext which just exposes the two tables:
public DbSet<User> Users { get; set; }
public DbSet<AuditEntry> AuditEntries { get; set; }
What I want to do is load a list of AuditEntry objects containing the message and the related User object containing the UserID and Name properties.
List<AuditEntry> auditEntries = db.AuditEntries.ToList();
Because I have my navigation properties marked as virtual and I haven't disabled lazy loading, I get an infinitely deep object graph (each AuditEntry has a User object, which contains a list of the AuditEntries, each of which contains a User object, which contains a list of AuditEntries etc)
This is no good if I then want to serialize the object (for example to send as the result in a Web API).
I've tried turning off lazy loading (either by removing the virtual keywords from my navigation properties in the model, or by adding this.Configuration.LazyLoadingEnabled = false; to my DBContext). As expected this results in a flat list of AuditEntry objects with User set to null.
With lazy loading off, I've tried to eager load the User like so:
var auditentries = db.AuditEntries.Include(a => a.User);
but this results in the same deep / cyclic result as before.
How can I load one level deep (e.g. include the user's ID and name) without also loading back-references / following navigation properties back to the original object and creating a cycle?
After much hacking, I've come up with the following potential solution using a dynamic return type and projection in my Linq query:
public dynamic GetAuditEntries()
{
var result = from a in db.AuditEntries
select new
{
a.AuditEntryID,
a.Message,
User = new
{
a.User.UserID,
a.User.Username
}
};
return result;
}
This produces (internally) the following SQL which seems sensible:
SELECT
[Extent1].[AuditEntryID] AS [AuditEntryID],
[Extent1].[Message] AS [Message],
[Extent1].[UserID] AS [UserID],
[Extent2].[Username] AS [Username]
FROM [dbo].[AuditEntries] AS [Extent1]
INNER JOIN [dbo].[Users] AS [Extent2] ON [Extent1].[UserID] = [Extent2].[UserID]
This produces the results that I'm after, but it seems a bit long winded (especially for real life models that would be significantly more complex than my example), and I question the impact this will have on performance.
Advantages
This gives me a lot of flexibility over the exact contents of my returned object. Since I generally do most of my UI interaction / templating on the client side, I frequently find myself having to create multiple versions of my model objects. I generally need a certain granularity over which users can see which properties (e.g. I might not want to send every user's email address to low-privilege user's browser in an AJAX request)
It allows entity framework to intelligently build the query and only select the fields that I have chosen to project. For example, inside each top level AuditEntry object, I want to see User.UserID and User.Username but not User.AuditEntries.
Disadvantages
The returned type from my Web API is no longer strongly typed so I couldn't create a strongly typed MVC view based on this API. As it happens this is not a problem for my particular case.
Projecting manually in this way from a large / complex model could result in a lot of code, seems like a lot of work and has the potential to introduce errors in the API. This would have to be carefully tested.
The API method becomes tightly coupled with the structure of the model and since this is no longer fully automated based on my POCO classes, any changes made to the model would have to be reflected in the code that loads them.
Include method?
I'm still a little confused about the use of the .Include() method. I understand that this method will specify that related entities should be "eager loaded" along with the specified entity. However, since the guidance seems to be that navigation properties should be placed on both sides of a relationship and marked as virtual, the Include method seems to result in a cycle being created which has a significant negative impact on it's usefulness (especially when serializing).
In my case the "tree" would look a little like:
AuditEntry
User
AuditEntries * n
User * n
etc
I'd be very interested to hear any comments about this approach, the impact of using dynamic in this way or any other insights.

Is it possible to store a struct's fields in the same table as the containing class?

I'm currently using Entity Framework 4 with the June 2011 CTP (for enum support) and I'm having difficulty with embedding a struct in a persisted class. I have a Patient class with an InclusionCriteria struct field (among others):
public class Patient
{
public InclusionCriteria inclusionCriteria
{
get;
set;
}
...
}
The struct is fairly simple, with primitive fields:
public struct InclusionCriteria
{
public bool withStemi
{
get;
set;
}
...
}
After running the system, it became apparent that the struct's data was not being saved. When I view the generated table, the struct is not there (as a foreign key or otherwise). I would like the struct's fields to be located in the Patient table, so I haven't made a DbSet for the criteria. I could potentially do this, but I'd rather keep it all in the same table. Is this possible in the entity framework?
Structs are not supported. You must use class and map it as complex type. If you are using code first approach you can try to make it class and simply recreate database - if you are lucky it will be mapped as complex type automatically. Otherwise you can use data annotation:
[ComplexType]
public class InclusionCriteria { ... }
or fluent API:
modelBuilder.ComplexType<InclusionCriteria>();
If you are using EDMX follow this article to create complex type and this article to use it.
Btw. CTP 2011 is only for testing new features, not for real development. Its content can change in next CTP.