Entity Framework, mapping Views to Tables - linq

I have a basic view that returns the same columns as a table (give or take 1 field)
in my DAL code, i am returning a list of MyTableObject, however in some cases, i will call the view to return the same data, but from different sources.
List<MyTableObject> tableObjects = new List<MyTableObject>();
if (case1)
tableObjects = entities.MyTableObjects.Where(criteria).ToList();
else
tableObjects = entities.MyViewObjects.Where(criteria).ToList(); // <-- This will obviously break
return tableObjects;
is there a way to Map view entities to be returned as table entities? (other than having table and view implement the same interface and return that interface) i would like to keep the return type as MyTableObject.
I came across Auto Mapper, but not sure if it would be suitable for this scenario..

Looks like i found a cool solution to this..
Initially I tried to implement interface approach and run into some casting issues (using interfaces alongside my predicate builder), and also with interfaces having to create partial classes for each entity that implement the interface..
the answer.. POCOs.
Iused Poco Template for EF, and than simply edited xxxPocoGenerator.Context.tt to return MyTable object from MyViews collection (one line).
public ObjectSet<Trade> v_Trade {
get { return _v_Trade ?? (_v_Trade = CreateObjectSet<Trade>("Trades")); }
}
nice and easy..

You can write a stored procedure (or CommandText in the model, without creating DB Object) that will simply call "Select * from View". Then create Function Import for this procedure and set the return type to MyTableObject.

Related

Linq to entities custom function in select

In Linq to Entities one can't use standard c# method to modify the results in the "select" clause, canonical functions are required.
I need to invoke such query:
CoreEntities.Contracts.Select(
c=> new {
c.Name,
c.Type,
Role = MapToRole(c));
private string MapToRole(Contract contract) {
switch(contract.Type) {
case: CTypes.Main: return "somerole1";break;
case: CTypes.Secondary: return "somerole2";break;
// ...
default: break;
}
return "none";
}
The "MapToRole" is a C# method created just to declutter the linq query.
Is there a way to create a custom c# function that would be accepted by Entity Framework "linq to Entity" parser?
I've found a solution for query filters but not for data formatting.
It appears that as it's a simple transformation, there's no reason this needs to be translated by the provider. I would suggest simply adding AsEnumerable() before your Select() to "detach" your projection from the provider.
Alternatively you could have a CTypes property in your data type and a method/property that performs the transformation of that within your model.
As a side note, doing this particular transformation in your application layer means that you're only pulling through the enum value, not a string - therefore less data from the provider.

AutoMapper Project().To() not working for interface destination

I have a situation in AutoMapper where I need to create a mapping with an interface destination. This is not a problem, and when using the normal Mapper.Map, it returns a proxy class as expected. However, when I try to do something similar with .Project().To(), which I need to use because an ORM is involved, I have issues. Here is the exact code that is failing which I replicated in a unit test:
AutoMapper.Mapper.CreateMap<RoleDto, IRole>(); //both just have Id/Name
IQueryable<RoleDto> roleDtos = new List<RoleDto>
{
new RoleDto { Id = 1, Name = "Role1" },
new RoleDto { Id = 2, Name = "Role2" }
}.AsQueryable();
//this works:
List<IRole> roles = roleDtos.Select(
roleDto => AutoMapper.Mapper.Map<IRole>(roleDto)
).ToList();
//this does not work:
List<IRole> roles2 = roleDtos.Project().To<IRole>().ToList();
I'm getting ArgumentException:
ArgumentException: Type 'UnitTestProject5.IRole' does not have a default constructor
In my real implementation the .Select is being performed on an Entity Framework collection, which is why I need to stick with .Project().To().
I have no issues with .Project().To() if the destination is not an interface. Additionally, I have no issues with the interface destination if I use .Map().
How can I get the interface destination and .Project.To() to work at the same time? Why is .Project.To() not giving me proxy classes like .Map() is? Any ideas?
Thanks!
Mapper.Map() takes the linq-to-objects route to materialize objects. As you said, AutoMapper is capable of creating types on the fly if the mapped target is an interface.
Project().To() is a way to translate the whole query, including the mapping, into SQL. Which is great, because only the properties that are required for the target object are included in the SQL query. However, the things AutoMapper does for creating types on the fly (undoubtedly some Refection voodoo) can never be part of an expression tree that can be converted into SQL. That's why Project.To simply tries to new up an object, even if it's an interface.
You'll have to use a concrete type as a mapping target. Of course, this type can implement an interface, so you can keep the independence you want.

Intercepting context.SaveChanges() in MVC 3 so that I can modify and use a custom sql query instead

I am working on an MVC3 project whose model is designed using Code First approach. I am using EF4 for ORM and have a need where I need two thing -
1. Intercept the context.SaveChages method
2.Do my own custom update query for one specific entity type only.
I got the first part working by overriding the SaveChanges() method like -
public override int SaveChanges()
{
var modifiedItems = this.ChangeTracker.Entries().Where(e => e.State == System.Data.EntityState.Modified && e.Entity is myEntityName);
foreach (var item in modifiedItems)
{
//ToDo: Write UPDATE Sql Query here
}
return base.SaveChanges();
}
How can I write my update query?
Thanks!
This is not possible. You can only map custom stored procedures to be used instead of CUD operations (only with EDMX) generated by EF but still you will have single stored procedure call per each operation and entity instance.

Can I include a convenience query in a Doctrine 2 Entity Method?

I'd like to include some additional functions in my Doctrine 2 entities to contain code that I'm going to have to run quite frequently. For example:
User - has many Posts
Post - has a single user
I already have a function $user->getPosts(), but this returns all of my posts. I'm looking to write a $user->getActivePosts(), which would be like:
$user->getPosts()->where('active = true') //if this were possible
or:
$em->getRepository('Posts')->findBy(array('user'=>$user,'active'=>true)) //if this were more convenient
As far as I can tell, there's no way to get back to the entity manager though the Entity itself, so my only option would be
class User {
function getActivePosts() {
$all_posts = $this->getPosts();
$active_posts = new ArrayCollection();
foreach ($all_posts as $post) {
if ($post->getActive()) {
$active_posts->add($post);
}
}
return $active_posts;
}
However, this requires me to load ALL posts into my entity manager, when I really only want a small subset of them, and it requires me to do filtering in PHP, when it would be much more appropriate to do so in the SQL layer. Is there any way to accomplish what I'm looking to do inside the Entity, or do I have to create code outside of it?
I think you should implement the method on the PostRepository rather than on the entity model.
I try to keep all model related logic in the repositories behind "domain specific" methods. That way if you change the way you represent whether a post is active or not, you only have to change the implementation of a single method instead of having to find all the active = true statements scattered around in your application or making changes in an "unrelated" entity model.
Something like this
PostRepository extends EntityRepository {
public function findActiveByUser($user){
// whatever it takes to get the active posts
}
}

Order By property from dynamic linq

I am using dynamic linq to make a generic class for processing a generic JqGrid from MVC all works fine (searching, pagination etc) except for sorting on code properties. Sorting works fine when I am hitting the DB to sort the data, but as soon as it is a property I have made the sorting does not work eg
public partial class tblStockOrder
{
public string approved
{
get
{
return approved_id == null ? "" : "Approved";
}
}
}
I am running the following Dynamic Linq
items = items
.OrderBy(string.Format("{0} {1}", sidx, sord))
.Skip(pageIndex * pageSize)
.Take(pageSize);
Where sidx etc are strings passed in by jquery.
So basically what is the best solution for handling a case where some properties will be from the db while others will be code properties (not sure of the correct naming). I can handle all this in code using reflection but would obviously like the DB to handle as much of the searching / sorting as possible without pulling in thousands of records and sorting through them in code using reflection.
Computed class will of course not work, as you're trying to create record which is part in memory, part in database.
You can, however, compute the same on database by specifying the function in linq query, example:
items = items
.OrderBy(x=> x.approved_id != null )
.Skip(pageIndex * pageSize)
.Take(pageSize);

Resources