Using linq select in DDD style entities - entity-framework-core

Hello everyone I have question related to EF Core and DDD style entities that I have not found any proper answer about it.
Despite these two facts:
1- Repositories should return POCO entities(not DTO).
2- Domain Entities should have properties with private setter.
In my case I have to use linq select in order to choose specific column from my table so I must use linq select.
In spite of private setters, what is the best way to do this?
Should I create custom method for each custom select?

Related

How can I use SQL many-to-many table from Entity Framework?

I am developing for an existing application which uses a SQL database that is used by two applications. One uses Entity Framework to connect to the database. The other uses LINQ-to-SQL. The SQL database is designed so that there are some tables showing many-to-many relationships between rows in two tables. Entity Framework seems not to import these tables, apparently because it has some object-oriented idea for how many-to-many relationships ought to be represented. So far, the Entity Framework application has not needed to know about those tables, but now it should. I don't know how that works, and I am concerned that even if I learn about Entity Framework's exciting new way to represent these relationships, that it won't cooperate nicely with the other application or the database which is designed to use the many-to-many table.
I.e., there is a table of Foos, and a table of Bars, and then a table with Foo and Bar Ids that lists which Foos relate to which Bars, and I don't want to stop using this relationship table, particularly because there is another LINQ application that heavily uses this relationship table.
Questions:
If I learn to use Entity Framework's many-to-many system, will it use and update the many-to-many table that the other application uses?
If not, what is a good way to get Entity Framework to not ignore the many-to-many relationship table, so I can write code to use the existing table?
Yes, Entity Framework will manage your many-to-many tables for you. Pure link tables (that only have two foreign key columns) in EF are represented as relationships as opposed to POCO objects. The way this is done is that you tell EF that there is a relationship between two of your objects and that table X is where this relationship is stored. As an example in EF 4.1. which is what I'm currently using this is done like so:
modelBuilder.Entity<Foo>() //Let me tell you about Foo...
.HasMany(f => f.Bars) //The property in the Foo class that links to Bar objects is Bars
.WithMany(b => b.Foos) //The property in the Bar class that links to Foo objects is Foos
.Map(m => {
m.MapLeftKey("FooID"); //Name of the foreign key column in the link table for Foo
m.MapRightKey("BarID"); //Name of the foreign key column in the link table for Bar
m.ToTable("FooBar"); //Name of the link table
});
You can then make changes to this table by linking/unlinking objects in your code. You pretty much do something like
myFoo.Bars.Add(myBar); //Add a row to the link table
myFoo.Bars.Remove(myBar) //Delete a row from the link table
For a full implementation you should google your version of EF.
In case of link tables that contain extra columns (for example a creation date) they are represented by a POCO just like all the other tables. If you're really paranoid about EF's ability to manage your link tables you can force it to go this route by adding a unique id column to your pure link tables, but I'd definitely advice against it.
Think of it this way: EF has been around for a while now and has achieved a certain degree of maturity. Combine this with the fact that many-to-many relationships are not exactly rare in databases. Do you really think the designers of EF haven't dealt with your case?

Entity Framework, Computed Entity Field

Is it possible to include a computed field in an EF entity? Example, lets say I have a shop selling products, and the products are grouped into categories.
When the list of categories is displayed for editing to the administrator of the shop I wish to list the number of products in each category as part of the list.
In NHibernate I would use a formula e.g.
<property name="Products" formula="dbo.Category_NumProducts(id)" />
I can't work out if something similar is possible for EF. I know I could make a category view and map this to a second entity but that seems wrong as its almost a complete duplication.
EDIT: If this isn't possible in EF, then what is the best way to accomplish this?
Unfortunately if your Category table doesn't have this as computed column you will not be able to map it without creating second entity - it leads to database view, defining query in EDMX or perhaps Query view in EDMX (but Query view may not work because you require aggregate function to be computed).
Edit:
IMHO the simplest solution (and also the best) is simply creating a ViewModel (some non mapped class) and use projection in Linq query:
var query = from c in context.Categories
where ...
select new CategoryView {
Id = c.Id,
Name = c.Name,
...
Products = c.Products.Count()
};

Entity framework: Database first/Code first hybrid

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.

Entity Framework STEs and many-To-many associations

I'm fairly new to EF and STE's, but I've stumbled on a painful point recently, and I'm wondering how others are dealing with it...
For example, suppose I have two STE's: Employee and Project. It's a many-to-many relationship. Each entity has a navigation property to the other (i.e. Employee.Projects and Project.Employees).
In my UI, a user can create/edit an Employee and associate it with multiple Projects. When the user is ready to commit, a list of Employees is passed to the server to save. However, if an Employee is not added to the "save list" (i.e. it was discarded), but an association was made to one or more Projects, the ApplyChanges extension method is able to "resurrect" the Employee object because it was "connected" to the object graph via the association to a Project.
My "save" code looks something like this:
public void UpdateEmployees(IEnumerable<Entities.Employee> employees)
{
using (var context = new EmployeeModelContainer(_connectionString))
{
foreach (var employee in employees)
{
context.Employees.ApplyChanges(employee);
}
context.SaveChanges();
}
}
I've been able to avoid this issue to now on other object graphs by using FKs to manipulate associations as described here: http://blogs.msdn.com/b/diego/archive/2010/10/06/self-tracking-entities-applychanges-and-duplicate-entities.aspx
How does one handle this when a many-to-many association and navigation properties are involved?
Thanks.
While this answer's a year late, perhaps it will be of some help to you (or at least someone else)
The simple answer is this: do not allow Entity Framework to infer m:m relationships. Unfortunately, I'm not aware of a way of preventing this, only how to deal with it after the fact.
By default, if I have a schema like this:
Employee EmployeeProject Project
----------- --------------- ----------
EmployeeId ---> EmployeeId |--> ProjectId
Name ProjectId ----- Name
... ...
Entity Framework will see that my EmployeeProject table is a simple association table with no additional information (for example, I might add a Date field to indicate when they joined a project). In such cases, it maps the relationship over an association rather than an entity. This makes for pretty code, as it helps to mitigate the oft-referenced impedence mismatch between a RDBMS and object-oriented development. After all, if I were just modeling these as objects, I'd code it the same way, right?
As you've seen, however, this can cause problems (even without using STE's, which cause even MORE problems with m:m relationships). So, what's a dev to do?
(The following assumes a DATABASE FIRST approach. Anything else and you're on your own)
You have two choices:
Add another column to your association table so that EF thinks it has more meaning and can't map it to an association. This is, of course, bad design, as you presumably don't need that column (otherwise you'd already have it) and you're only adding it because of the particular peculiarities of the ORM you've chosen. So don't.
After your context has been generated, map the association table yourself to an entity that you create by hand. To do that, follow the following steps:
Select the association in the designer and delete it. The designer will inform you that the table in question is no longer mapped and will ask you if you want to remove it from the model. Answer NO
Create a new entity (don't have it create a key property) and map it to your association table in the Mapping Details window
Right-click on your new entity and add an association
Correct the entity and multiplicity values (left side should have your association entity with a multiplicity of *, right should have the other entity with a multiplicity of 1)
Check the option that says "Add foreign key properties to the Entity"
Repeat for the other entity in the association
Fix the property names on the association entity (if desired...not strictly necessary but they're almost certainly wrong) and map them to the appropriate columns in the Mapping Details window
Select all of the scalar properties on your association entity and set them as EntityKey=True in the Properties window
Done!

Entity Types not mapped but stored

I've a problem mapping just one table from database, I add several tables using "Update model from Database" function through Visual Studio 2010 interface, and everyone works as expected except one table!
Looking at "Model Browser" I can see the table doesn't appear under "Entity Types" but it is present under section "ObjectEntity.Store", so my POCO Generator create an entity related and I can't try to add it again from database but I can't access it through context (like context.table_name).
Tha table doesn't have particular form, there are just two key fields
Could someone help me?
Thanks
I guess it is junction table for implementing many-to-many relation, isn't it? In such case it is correct behavior. EF will hide this table because it is not needed in object oriented approach where many-to-many association can be modeled directly without helper entity. You will see in your model that those two related entities are connected by line with * - * multiplicity and each entity will contain navigation property which is collection of related entities. By manipulation with entities in these collections you are creating or removing records in that hidden table. That is the way how you work with such relation in EF.