I have a class like this:
public class GeneralClass
{
public int Id {get; set;}
public string Name {get; set;}
}
which is a pretty generic class. I also have a derived class like this:
public class DerivedClass: GeneralClass
{
public int SpecificProperty {get; set;}
public string AnotherSpecificProperty {get; set;}
public bool BooleanSpecificProperty {get;set;}
}
The problem is, I can have lots of derived classes (more than 10) in my app, that´s why inheritance in a database IS NOT AN OPTION.
The solution I came up with is to have GeneralClass as a table, with an XML column containing the specific properties.
Something like this:
CREATE TABLE
General(Id int primary key,
Name nvarchar(50),
SpecificProperties xml);
where the specific properties contain the properties of the derived class.
The question is: How can I SAVE and QUERY this xml column using Entity Framework, and deserialize the xml into the properties?
"...I can have lots of derived classes (more than 10) in my app, that´s why inheritance in a database IS NOT AN OPTION" - why not!?
There are two main inheritance patterns - table per hierarchy (TPH) and table per type (TPT). While the first one might seem quite a waste of SQL resources, the second one perhaps will match your requirements. There is one more pattern - table per concrete type (TPC), which may be considered a variation of TPT. You do not have abstract classes in your hierarchy, or at least the code snippet you've posted does not, so it is quite natural to use
TPT and query the way you're very familiar with, say LINQ to entities. More information about EF and inheritance patterns here and here.
Still, if you do insist on using XML you may declare the field as XML type (this is a column data type, which SQL server supports). You can query it like described here, here, and here.
Related
Right now I am learning a lot about the Entity Framework from Videos on Pluralsight, so excuse my Question which might look newbish but I can not understand what Complex Types are or why I would need them.
I do know that I have to map them via Annotations or Fluent Api something like this:
modelBuilder.ComplexType<blubb>();
Maybe someone could elaborate the need of Complex Types for me?
Assume you have an entity for Courses in a class, that entity has scalar properties of Location, Days and Time, but you find you want to abstract that so that other entities can use the same model. So you can create a complex type that contains Days, Location and Time give it a name: ComplexType1. Now other entities can use this type rather than individual scalar properties just by declaring ComplexType1 in the model definition.
Complex Types are repeating structural patterns in your database. You have to custom map them because there is no way for it to be inferred.
An example would be two tables that both have address related columns:
Company
CompanyName
AddressLine1
AddressLine2
Postcode
Account Manager
Name
TelephoneNumber
SuperiorName
AddressLine1
AddressLine2
Postcode
This is obviously not well-normalized database design but such situations do occur. You can abstract the model for address into a complex type, then specify that both Company and AccountManager have that complex type rather than keep mapping the matching (albeit separate in the database) columns for each table that has address columns.
Here's an in depth article on Complex Types: http://msdn.microsoft.com/en-gb/data/jj680147.aspx
And here is one that isn't quite so heavy, and shows the benefit of mapping two addresses on one model, things like that: http://visualstudiomagazine.com/articles/2014/04/01/making-complex-types-useful.aspx
Complex type are types that don't map to a table like entities instead they map to one or more fields.
The following complex type
public class Descriptor
{
public string Name {get;set;}
public string Description {get;set;}
}
And entity
public class MyEntity
{
public Descriptor { get;set;}
}
This would map to a table with Name and Description fields. It is a useful way to have a type encapsulate a common set of fields/properties you might want on several entities.
Scenario: I am writing a program that handles report generation.
I have the report stored in a database, mapped to an EF model. There are some non-database fields (i.e. some fields are auto-calculated based on other fields that ARE in the db). Would it make sense to have one class that solely maps to the DB, and another class that takes that information and additionally has the other calculating fields?
i.e. a sample class to interact with the codefirst database would be
public class Report{
public int CategoryOneSeverity {get; set;}
public int CategoryTwoSeverity {get;set;}
public string Title {get;set;}
}
Would it make sense to make another class, like:
public class ReportModel{
public int CategoryOneSeverity;
public int CategoryTwoSeverity;
public string Title;
public int RiskRating{
get{ return CategoryOneSeverity + CategoryTwoSeverity; }
}
}
Or should the RiskRating property be in the EF model.
Yes, I absolutely believe you should have different classes to model your domain than your DB. Unless your application is extremely trivial, if you try to map your domain objects directly, you invariably have to change them to match what you need your data structure to be, and possibly expose things you don't want to expose. Think of it as a violation of the Single Responsibility principle; your class has two reasons to change if you make it your domain object and map it directly. One is in response to changing business requirements, the other is in response to changing data storage schema.
"Would it make sense to have one class that solely maps to the DB, and
another class that takes that information and additionally has the
other calculating fields?"
Most likely yes. Usually I would create a new class suffixed with "ViewModel" such as HumanResourcesReportViewModel if my entity class was HumanResourcesReport.
There's lots of variations on how to use ViewModels, and we could get into a pedantic debate about terminology, but conceptually, take your entity and create a new class with that data plus whatever additional information you need to process the report. In this case the report generation is in a way the View of the MVC model, so I don't think it's offensive to call the class holding the data a ViewModel.
Are you using Code First or DB First?
You can have auto calculated fields in your model, which are not mapped to fields in the database.
It also depends on your architecture. If you're using DB first, refreshing your EF model would update your EF classes, losing your mapped fields. In the DB-First scenario, an alternative would be to use the EF model class as your base class and inherit from it for your report class.
public class ReportModel
{
public int CategoryOneSeverity;
public int CategoryTwoSeverity;
public string Title;
}
public class ReportClass : ReportModel
{
public int RiskRating
{
get { return CategoryOneSeverity + CategoryTwoSeverity; }
}
}
Say I have the below entities. (Heavily Simplified for brevity, but the key properties are included)
public class Crime
{
[Key]
public int CrimeId {get;set;}
public virtual ICollection<Victim> Victims {get;set;}
public virtual CrimeDetail Detail {get;set}
}
public class Victim
{
[Key]
public int VictimId {get;set;}
public string VictimCategory {get;set;}
}
public class CrimeDetail
{
[Key]
public int id {get;set;}
public string DetailText {get;set;}
}
I have 600,000+ of these records to insert into SQL Server 2008 Express R2, which takes quite some time using Entity Framework 4.4.
Ideally I'd like to use SQLBulkCopy to batch insert these records, but since that doesn't support complex types (At least not out of the box), then I'm trying to find some other potential solutions.
I'm open to changing my model if necessary.
EDIT: would the AsDataReader Extension method from MSDN help in this instance?
When having the same issue we end up having code-first generated database with EF and strongly typed generated datasets to be used for SQLBulkCopy.
(We never really coded those classes, they were generated using xsd util from xsd definition of 1-10gb xml file. I'm trying to recall right now when we havent generated typed datasets from the same xsd, but that seems irrelevant to your issue.)
Depending on how you are getting those 600k+ records you either can change the code to use generated strongly-typed datasets or use some object-to-object mapper to map your EF POCO objects to datasets as properties going to be named the same.
Here is a link on generating strongly typed datasets.
Here is an example how to use SqlBulkInsert.
So, I'd love some feedback on the best way to design the classes and store the data for the following situation:
I have an interface called Tasks that looks like this:
interface ITask
{
int ID{ get; set;}
string Title {get; set;}
string Description{get; set;}
}
I would like the ability to create different types of Tasks depending on who is using the application...for example:
public class SoftwareTask: ITask
{
//ITask Implementation
string BuildVersion {get; set;}
bool IsBug {get; set;}
}
public class SalesTask: ITask
{
//ITask Implementation
int AccountID {get; set;}
int SalesPersonID {get; set;}
}
So the way I see it I can create a Tasks table in the database with columns that match the ITask interface and a column that shoves all of the properties of more specific tasks in a single column (or maybe even serialize the task object into a single column)
OR
Create a table for each task type to store the properties that are unique to that type.
I really don't like either solution right now. I need to be able to create different types of Tasks ( or any other class) that all share a common core set of properties and methods through a base interface, but have the ability to store their unique properties in a fashion that is easy to search and filter against without having to create a bunch of database tables for each type.
I've starting looking into Plug-In architecture and the strategy pattern, but I don't see where either would address my problem with storing and accessing the data.
Any help or push in the right direction is greatly appreciated!!!
Your second approach (one table per type) is the canonical way to solve this problem - while it requires a bit more effort to implement it fits better with the relational model of most databases and preserves a consistent and cohesive representation of the data. The approach of using one table per concrete type works well, and is compatible with most ORM libraries (like EntityFramework and NHibernate).
There are, however, a couple of alternative approaches sometimes used when the number of subtypes is very large, or subtypes are created on the fly.
Alternative #1: The Key-Value extension table. This is a table with one row per additional field of data you wish to store, a foreign key back to the core table (Task), and a column that specifies what kind of field this is. It's structure is typically something like:
TaskExt Table
=================
TaskID : Number (foreign key back to Task)
FieldType : Number or String (this would be AccountID, SalesPersonID, etc)
FieldValue : String (this would be the value of the associated field)
Alternative #2: The Type-Mapped Extension Table. In this alternative, you create a table with a bunch of nullable columns of different data types (numbers, strings, date/time, etc) with names like DATA01, DATA02, DATA03 ... and so on. For each kind of Task, you select a subset of the columns and map them to particular fields. So, DATA01 may end up being the BuildVersion for a SoftwareTask and an AccountName for a SalesTask. In this approach, you must manage some metadata somewhere that control which column you map specific fields to. A type-mapped table will often look something like:
TaskExt Table
=================
TaskID : Number (foreign key back to task)
Data01 : String
Data02 : String
Data03 : String
Data04 : String
Data05 : Number
Data06 : Number
Data07 : Number
Data08 : Number
Data09 : Date
Data10 : Date
Data11 : Date
Data12 : Date
// etc...
The main benefit of option #1 is that you can dynamically add as many different fields as you need, and you can even support a level of backward compatibility. A significant downside, however, is that even simple queries can become challenging because fields of the objects are pivoted into rows in the table. Unpivoting turns out to be an operation that is both complicated and often poorly performing.
The benefits of option #2 is that it's easy to implement, and preserves a 1-to-1 correspondence betweens rows, making queries easy. Unfortunately, there are some downsides to this as well. The first is that the column names are completely uninformative, and you have to refer to some metadata dictionary to understand which columns maps to which field for which type of task. The second downside is that most databases limit the number of columns on a table to a relatively small number (usually 50 - 300 columns). As a result, you can only have so many numeric, string, datetime, etc columns available to use. So if you type ends up having more DateTime fields than the table supports you have to either use string fields to store dates, or create multiple extension tables.
Be forewarned, most ORM libraries do not provide built-in support for either of these modeling patterns.
You should probably take a lead from how ORMs deal with this, like TPH/TPC/TPT
Given that ITask is an interface you should probably go for TPC (Table per Concrete Type). When you make it a baseclass, TPT and TPH are also options.
I'm beginning work on a new project that's would be much easier if there was some way to make different data models polymorphic. I'm looking at using the Entity Framework 4.0 (when it's released), but have been unable to determine if it will actually be able to work.
Here's the basic scenario. I'm implemented a comment system, and would like to be able to connect it to many different types of models. Maybe I want comments on a person's profile, and comments on a webpage. The way I would do this in the past is to create relationships between the person table and the comment table separately from the relationship between the webpage table and the comment table. I think this leads to an overly complicated table structure in the database, however.
It would be best if I could just be able to add an interface to the objects I want comments on, and then simplify the table structure in the database to a single relationship.
The problem I'm running into is that I don't seem to know the right terminology in order to find information about how to do this type of thing. Any help anyone can provide would be greatly appreciated.
If you design your "comments table" to be comment-type-agnostic (just the basics, like an id, date & time, and text content), you can then use a single additional table that maps them all.
public interface ICommentable
{
int CommentTypeCode
int Id
...
}
Now that mapper table contains columns:
comment_type_code
target_object_id
comment_id
Your comments all go in one table, with an Id
Your various "target objects" must all have an Id of the same type
Now you can arbitrarily add new "commentable" objects to your system without changing the comments table or the mapper table -- just assign it a new type code and create the table with the requisite Id column.
I accomplish this with LinqToSql and partial classes. For each class that I want to implement an interface, I go to create a non-tool-generated file that contains part of the partial class that declares the class to implement the interface.
For example:
Generated code:
// this code is generated by a tool blah blah
partial class FooComment {
// all the generated crap
string Author {
// ...
}
// etc
}
The interface:
interface IComment{
string Author{ get; }
// etc
}
My code:
// lovingly hand-written by me
partial class FooComment : IComment {
}
Now, if you want to cast any group of FooComments to IComment, use the Cast linq extension method:
db.FooComments.Cast<IComment>()