doctrine query in model or controller? - model-view-controller

I'm using Codeigniter and Doctrine together for a project. I've gotten everything set up with both of these tools. But I'm not sure where I should have this bit of code:
$query = $em->createQuery('SELECT u FROM sessions u');
$sessions = $query->getResult(); // array of User objects
Should I be putting this in the controller or in the models/entities? At first thought, I figured I should put this kind of logic in the Sessions model, but it requires the entities manager $em, which I had thought should have been in the controller.
Thanks, this has been driving me crazy for the past half hour.

A lot of people like to create objects called DAOs or Data Access Objects to store this type of information.
The DAO contains the entity manager and methods that can be called and return the data you need. For example this function would reside in a DAO:
function findEmployeeById($emp_id)
And it would contain the query used to retrieve an employee from the database. In your controller you would just use the DAO instead of having an entity manager and dealing with it at that level.
But it really depends on preference and how large your project is.

Related

Joining tables in two separate databases with .Net Core 2.1 / EF Core

I have a .Net Core 2.1 Web API which talks to two MySQL databases. Therefore I have two DbContexts, each with a connection string pointing to the relevant database.
In one of my controller actions, I need to return data which requires a join between two tables, one from each database. Is it possible to do this?
As an example, a simple controller action to retrieve data might look something like this:
[HttpGet]
public IEnumerable<Employee> GetEmployees()
{
return _context.Employees
.Include(e => e.Departments);
}
That example uses one controller only, because in that example both the employee and department tables are in the same database, and therefore both their DbSets would be in the same DbContext.
But what if the employee table was in one database and department table was in another? Then the DbSets for employee and department would be defined in different DbContexts. How could I handle the join in that case? (So that in the example above, the "Include" works properly?
I would imagine that I would have to inject both DbContexts into this controller. But I'm not sure where to go from there...
In my case, both datbases are MySQL databases, and both are on the same server, so that is the only scenario I'm interested in.
After more research, it looks like I could maybe use raw SQL to achieve this. However, what I ended up doing is creating a view on the server which does all the necessary joins, and then I simply call this view...

How to link an entity with database?

I have a complex entity with many relations, so I need many forms in many pages to create one. Therefore, I use a session to keep my entity.
Everything is going okay, but when comes the time to flush, the entity manager returns the "entity through relationship is not configured to cascade persist" thinking that some entities are new but they're actually stored in db !
For instance, I create a User with a ManyToOne Group, using $u->setGroup(Group $group); ($group being an existing group from the db). When I put it in session, then get it back in another page and then flush it, the entity manager tries to create a whole new group, not knowing that it is an existing one in db.
I use a little trick to overcome this :
$u = $this->get('session')->get('userToAdd');
$group = $em->getRepository('MyBundle\Entity\Group')->find($u->getGroup()->getId());
$u->setGroup($group);
With this, EM will recognize the group stored in db and the flush will go just fine, but with my entity having so much relationships like this, it is very convenient to do this for every single one.
Any ideas for this issue ?
Before find group try to refresh $u object.
$em->refresh($u)
You have to do:
$em->merge($u);

Is it possible to map Linq queries from one Data Model to a query over a different data model?

I would like to provide an OData interface for my application. The examples that I have seen use EF to map the LINQ queries to SQL queries.
IMHO it this approach pretty much exposes the physical database model to the world (I know EF/NH give some flexibility, but it is limited).
What I would like the be able to do, is the following:
Define my Data Contract via some DTOs.
Have a OData Service that will let users query over my Data Contract Dtos.
Have some translation layer to translate the queries over the DTOs to queries over, let's say, EF model or NH.
Execute the translated query.
Map the results back to my Data Contracts.
Am I out of my mind or is there a solution to this problem?
I have 2 models, the "contract" model and the "persisted" model. The persisted model is what Entity Framework is mapped to. The Get method that returns an IQueryable returns a IQueryable which is just something along the lines of:
return dbContext.PersistedCustomers.Select(x => new Customer(Name = x.OtherName, ...));
At least when using DbContext as opposed to ObjectContext, Where criteria based on the contract model get translated automatically into Where criteria of the PersistedModel to be executed against the database. Hopefully the differences between the two aren't that complex that you need some weird data massaging. I'm sure there's limits to the reversal it does.
One way of doing it would be to create a ViewModel that will represent your Model and then use AutoMapper to map between them. You can use like this:
var address = _Context.Addresses.Where(p => p.AddressID == addressID).Single();
AddressVM result = Mapper.Map<AddressVM>(address);

MVC3, EF4, and Using blocks

Advocation for using blocks with Entity Framework seems to be popular, but this tutorial for MVC show the Object Context for the Entity being created once at the class level. I ran into the latter first, so I had been using it. I am now trying to switch to the using block method to see if it really is faster, but am running into this error on the view:
The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
The view is trying to access a collection that was created by this:
homeView.UserList = new SelectList((from n in db.Users where n.US_INACTIVE == 0 orderby n.US_FULL_NAME select n).AsEnumerable(), "US_USER_ID", "US_FULL_NAME");
I don't understand why it is still trying to access the object context from the view (when it uses that SelectList) when it should have been populated in the controlled. Even more confusing, is this same problem does not occur for other database-populated data, which appears to make it into the view just fine.
That aside though, what do I need to do to get data from a using block into the view properly? Or, is a using block the wrong way to go for MVC, and should I just keep using once object context for the class?
You probably didn't call .ToList at the end of your expression so you are not eagerly executing any query but only building query expressions. It is only once the view is executed that the query is implicitly executed, but that happens long after your controller life has ended as well as any data contexts.
This being said I consider passing domain models to views as a bad practice. You should be using view models which are classes specifically designed to the requirements of a given view.
Ayende Rahien has a series of blog posts about the issues of view models. The view model that you pass to the view from the controller must contain all the necessary properties eagerly initialized and loaded with data and this independently of the data access technology you are using. And by the way it's not the controller's responsibility to manage your EF data contexts lifetime. That's should be specific to your data access layer (the repository).
Are you using another table in your view that is related to Users? In your current query only the Users table will be populated and accessing data in any related table will throw that error.
homeView.UserList = new SelectList((from n in db.Users.Include("Other Table") where n.US_INACTIVE == 0 orderby n.US_FULL_NAME select n).AsEnumerable(), "US_USER_ID", "US_FULL_NAME");

how can get data from another Table

I am designing a project in asp.net mvc3, i have designed my database in sql server, add i am using ado.net.
This is my controller action
public ViewResult ProductFormulationIndex()
{
return View(db.ProductFormulation.ToList());
}
means i want to display all fields of ProductFormulation table.
this is my table:-
and this is my productCategory Table
in my ProductFormulationIndex.cshtml i want to display Code of ProductCategory Table, not only id. So what should i do in controller or in Model for it ?
you may suggest tutorial related to it.
Thanks in advance.
You need a view model which is specifically designed for the view.
When defining your view models you shouldn't be thinking in terms of tables. SQL tables have absolutely no meaning in a view. Think in terms of what information you need to show and define your view models accordingly.
Therefore, You can define a view model like:
public class ProductInformation
{
...
public string CategoryCode {get; set;}
...
}
Or public Category ProductCategory.
You can use AutoMapper to convert between your real models and the view model you have defined.
You can find a good tutorial at http://weblogs.asp.net/shijuvarghese/archive/2010/02/01/view-model-pattern-and-automapper-in-asp-net-mvc-applications.aspx
Although I may not answer your question you are touching on some interesting points.
I subscribe to the school of thought that says one should not query an object model but rather make use of a denormalized lightweght query layer.
You will pobably quickly run into the lazy-loading and projection issue: i.e. you do not always require the related data and you do not always require all the fields. A query layer takes care of this quite nicely since using a denormalized model means that when you do your query you do not need to do N-number of joins to get the related data. You will still at some point need to gather up the data but you actual view queries will be order fo magnitude faster.
Also, getting all the data (by joining) for your denormalized model is a once-off affair as opposed to doing it each and every time you display the relevant data on the front-end.
Hope that makes sense :)

Resources