Entity framework: Database first/Code first hybrid - entity-framework

I am trying to create a custom Entity Framework (4.2) entity that would be mapped to my database like it would be done in a Code first approach.
The issue is that my entity framework data model is using Database first.
How can I add my custom entity to entity framework's context?

If by the Database first you mean that you already have EDMX created from exiting database you simply cannot use code first. You must create table and update model (EDMX) from the database to include it in EDMX.
Edit based on comment:
I want to create a BriefUser entity that would basically be a lighter
version of User but it would have properties retrieved from User's
foreign keys.
Well this is possible. You can either create BriefUser as common class and use projection in query.
var breifUser = (from x in context.Users
where ...
select new BriefUser
{
// Fill BreifUser's properties here
}).FirstOrDefault();
You can even refactor former code to reusable extension method:
public static IQueryable<BriefUser> ProjectUser(this IQueryable<User> query)
{
return query.Select(x => new BreifUser()
{ // Fill BreifUser's properties here });
}
and use it like:
var briefUser = context.Users.ProjectUser().FirstOrDefault(...);
It is also possible to define your new class as "entity view". The first problem is that each table can be mapped to only one entity (except some advanced concepts like inheritance or splitting) so you cannot define your BriefUser as a new entity type because mapping both User and BriefUser to UserTbl would violate this rule. You must use special construct called QueryView.
QueryView is view in mapping level. It allows you to create new mapped type which is projection of existing mapped entities defined directly in EDMX's MSL part. The projection is defined as custom Entity SQL query. The problem is that QueryView has limitations:
It doesn't offer all Entity SQL features - for example it doesn't support aggregations (which I consider as really missing feature). Without aggregations you for example cannot create a new type which will contain property counting some related entities.
It is not supported in designer. You must edit your EDMX as XML to define QueryView and you must write Entity SQL query yourselves.
Resulting type is a "view" and it is read-only.
I want to keep the EDMX file, but also be able to add an entity
(BriefUser) to EF's context.
This is not possible. Your BreifUser is only projection / view and EF is not able to track changes back to originating tables so you cannot add BreifUser to context and persist it. In case of QueryView you can achieve it if you define custom stored procedures which will no how to decompose BreifUser and modify all related tables. These stored procedures must be imported to the EDMX and mapped to data modification operations of the view entity. Btw. same will happen if you map your entity to the database view because EF takes all views as read-only.

Related

DTO/POCO with Entity Framework

I'm using EF5 Model First. I don't really understand what are the auto-generated classes from the EDM. According to some documentation this classes are POCOs but why are they used in the context ?
Assuming I have a Student entity, then I get a Student POCO class and a DbSet StudentSet property in my context.
Will this next instructions put a POCO in my database ?
MyContext.StudentSet.Add(johndoe);
MyContext.SaveChanges();
So EF uses POCO to transfer data ? Actually I miss the step when POCO exchange data with entities or DTO and when the entities put data in the database.
The generated classes from the EDM is the ORM / Persistence classes. You use that classes to query / make changes from / to database. You need to translate any DTO object to POCO object when about making changes to database.
ORM is about mapping object to data in database, instead of dealing with insert into syntax to insert record to database in the application, you use StudentSet.Add to add a new data. The johndoe information will be translated into sql syntax, EF will map each property to each column when translating it into query.
The Add method will store the johndoe information as Added in the memory but it will not be executed right away to the database. If you have another Add method, it will be marked as Added too. The moment you call SaveChanges, all the changes will be saved into database by sending a generated query.
The mapping between DTO and EF entity happens before you add the johndoe. You might have another DTO class that is used in the UI. You need to map it manually or using mapper library to create a POCO object from a DTO object. For example:
// studentDto as parameter
var johndoe = new Student
{
Name = studentDto.StudentName,
Age = studentDto.StudentAge
};
MyContext.StudentSet.Add(johndoe);
// studentDto might have another information as well
var johndoeSubject = new Subject
{
Name = studentDto.SubjectName,
Years = studentDto.SubjectYears
};
MyContext.SubjectSet.Add(johndoeSubject);
MyContext.SaveChanges();

How should I deal with an EF code first model where no entities have keys?

I have used the Entity Data Model Wizard to generate an EF data model (an edmx with POCO's) based on the Object Catalogue Views in SQL Server, i.e. sys.objects, sys.tables, sys.columns, etc. When I try to access any data through my DbContext's DbSet properties, EF throws a ModelValidationException, complaining that entities don't have keys defined.
I can easily modify the T4 template that generates the entity POCOs to include a dummy property marked with the [Key] attribute, but this seems a bit klunky, as now my entity classes have a 'phantom' property that doesn't belong to them. Choosing a name for the key column is also an issue, but I could do something like generate a GUID for a unique key column name for ever class.
But, isn't there a better, neater way of telling EF I don't need key columns, as this model is strictly read only?
ADDENDUM: If I use the Entity Framework Power Tools - Reverse Engineer Code First tool, it creates a mapping class (derived from EntityTypeConfiguration) for each entity, and where the entity has no define key, it defines one using all the fields in the entity.

Select Specific Columns from Database using EF Code First

We have a customer very large table with over 500 columns (i know someone does that!)
Many of these columns are in fact foreign keys to other tables.
We also have the requirement to eager load some of the related tables.
Is there any way in Linq to SQL or Dynamic Linq to specify what columns to be retrieved from the database?
I am looking for a linq statement that actually HAS this effect on the generated SQL Statement:
SELECT Id, Name FROM Book
When we run the reguar query generated by EF, SQL Server throws an error that you have reached the maximum number of columns that can be selected within a query!!!
Any help is much appreciated!
Yes exactly this is the case, the table has 500 columns and is self referencing our tool automatically eager loads the first level relations and this hits the SQL limit on number of columns that can be queried.
I was hoping that I can set to only load limited columns of the related Entities such as Id and Name (which is used in the UI to view the record to user)
I guess the other option is to control what FK columns should be eager loaded. However this still remains problem for tables that has a binary or ntext column which you may not want to load all the times.
Is there a way to hook multiple models (Entities) to the same table in Code First? We tried doing this I think the effort failed miserably.
Yes you can return only subset of columns by using projection:
var result = from x in context.LargeTable
select new { x.Id, x.Name };
The problem: projection and eager loading doesn't work together. Once you start using projections or custom joins you are changing shape of the query and you cannot use Include (EF will ignore it). The only way in such scenario is to manually include relations in the projected result set:
var result = from x in context.LargeTable
select new {
Id = x.Id,
Name = x.Name,
// You can filter or project relations as well
RelatedEnitites = x.SomeRelation.Where(...)
};
You can also project to specific type BUT that specific type must not be mapped (so you cannot for example project to LargeTable entity from my sample). Projection to the mapped entity can be done only on materialized data in Linq-to-objects.
Edit:
There is probably some misunderstanding how EF works. EF works on top of entities - entity is what you have mapped. If you map 500 columns to the entity, EF simply use that entity as you defined it. It means that querying loads entity and persisting saves entity.
Why it works this way? Entity is considered as atomic data structure and its data can be loaded and tracked only once - that is a key feature for ability to correctly persist changes back to the database. It doesn't mean that you should not load only subset of columns if you need it but you should understand that loading subset of columns doesn't define your original entity - it is considered as arbitrary view on data in your entity. This view is not tracked and cannot be persisted back to database without some additional effort (simply because EF doesn't hold any information about the origin of the projection).
EF also place some additional constraints on the ability to map the entity
Each table can be normally mapped only once. Why? Again because mapping table multiple times to different entities can break ability to correctly persist those entities - for example if any non-key column is mapped twice and you load instance of both entities mapped to the same record, which of mapped values will you use during saving changes?
There are two exceptions which allow you mapping table multiple times
Table per hierarchy inheritance - this is a mapping where table can contains records from multiple entity types defined in inheritance hierarchy. Columns mapped to the base entity in the hierarchy must be shared by all entities. Every derived entity type can have its own columns mapped to its specific properties (other entity types have these columns always empty). It is not possible to share column for derived properties among multiple entities. There must also be one additional column called discriminator telling EF which entity type is stored in the record - this columns cannot be mapped as property because it is already mapped as type discriminator.
Table splitting - this is direct solution for the single table mapping limitation. It allows you to split table into multiple entities with some constraints:
There must be one-to-one relation between entities. You have one central entity used to load the core data and all other entities are accessible through navigation properties from this entity. Eager loading, lazy loading and explicit loading works normally.
The relation is real 1-1 so both parts or relation must always exists.
Entities must not share any property except the key - this constraint will solve the initial problem because each modifiable property is mapped only once
Every entity from the split table must have a mapped key property
Insertion requires whole object graph to be populated because other entities can contain mapped required columns
Linq-to-Sql also contains ability to mark a column as lazy loaded but this feature is currently not available in EF - you can vote for that feature.
It leads to your options for optimization
Use projections to get read-only "view" for entity
You can do that in Linq query as I showed in the previous part of this answer
You can create database view and map it as a new "entity"
In EDMX you can also use Defining query or Query view to encapsulate either SQL or ESQL projection in your mapping
Use table splitting
EDMX allows you splitting table to many entities without any problem
Code first allows you splitting table as well but there are some problems when you split table to more than two entities (I think it requires each entity type to have navigation property to all other entity types from split table - that makes it really hard to use).
Create stored procedures that query the number of columns needed and then call the stored procs from code.

How to model a n to m relation with an attribute in Entity framework without adding the extra table

I'm pretty new to the Entity framework and I'm modelling this simple structure:
With this model what I have is a Users class with a property UsersGroups (a collection of UserGroups objects).
I would like to have a Users class with a property like Groups with type Tuple or something like this (a new PriorizedGroup class, etc) that is much more related with the bussines.
Is this possible with the Entity framework?
Thanks in advance.
EDIT: If I were modeling the bussines objects I would create a User class with a Groups property that contained all the groups the user pertains with an extra property to store its priority (with a tuple, with an inherited class, as you wish). The thing is that I feel that the objects created by the Entity framework resemble the SQL structure, not the business structure.
Not directly. EF can map the relation only in the way you see it at the moment but you can add your custom behavior to your partial part of the entity. The simple way is something like
public partial class Users
{
public IEnumerable<PrioritizedGroup> Groups
{
get
{
return UserGroups.Select(ug => new PrioritizedGroup
{
Priority = ug.Priority,
Id = ug.Group.Id,
Name = ug.Group.Name,
Description = ug.Group.Description
})
.OrderBy(g => g.Priority);
}
}
}
To make this happen directly in EF you need some advanced mapping technique which will require you to modify EDMX source code directly (either DefiningQuery or QueryView) and it will make the entity read only (you will need stored procedures for modification).
To make the collection exposed on Users updatable you would probably need to use ObservableCollection and transfer all modifications triggered by ObservableCollection back to original UserGroups collection. Once you have something like that implemented you can hide original collection.

ADO.NET Ef4- How can i map a entity to stored procedure without mapping to table

We are using ado.net entity framework 4.0 for our database layer and I am a newbie to ado.net entity framework. I have created entity via adding a entity in entity framework. I want to map that entity with stored procedure only not table of the database. Stored procedure will return same column as entity. How it is possible and how i can do that without mapping to table?
Here is a complete walkthrough http://msdn.microsoft.com/en-us/library/cc716679.aspx
Its not possible because an ObjectSet is an IQueryable and mapping an ObjectSet to stored procedure would not give u an IQueryable because stored procedures by their very nature cannot be composed. The best you can do is take the content inside the stored procedure and put into a view and map the view to an ObjectSet which is possible.
You need to create a complex type, not an entity. Open up the model browser and import your stored procedure as a "function import" (your SP must not use #tempTables but you can use #tableVariables instead); in the function import wizard you'll see a "create complex type" button.
The SP becomes a method in the model context and you can use it to get IEnumerable[TheComplexType].
In EF4.1 code-first it's even simpler, you put a [ComplexType] attribute on top of any class and you can use that type as a return type for context.ExecuteStoreQuery[T]. If your properties are named exactly as the returned columns are (and the types line up), the mapping is "magic" - it just works.