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

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.

Related

extending datamodel in Microstream

I would like to extend an existing datamodel in Microstream with a new data object. E.g. I have Customers, with data records in Microstream, and I would like to add Vendors, with their own datastructure and data. As the database is not empty, I cannot start as if their is no data, however adding a list of Vendor to the dataroot doesn't seem to work. Microstream says the list is null when starting, which is correct, but I cannot add my new object to a null list. Can someone explain me how to add a vendor to my 'database' ?
You just need to add this List and store this object with the existing list again.
I received an answer from fh-ms # Microstream:
Hi, you are right, the vendors list is not present in the storage, so the field will be initialized with its default value (null).
There are several possibilities to introduce initial values to new fields.
One rather complex way would be to implement a Legacy Type Handler.
A far more simple one is just lazy initialization in your Customer type:
public List<Vendor> getVendors()
{
if(this.vendors == null)
{
this.vendors = new ArrayList<>()
}
return this.vendors;
}
And that works !

hotchocolate throws error when using UseFiltering() on a field

I have a pretty simple setyp where I'm putting graphql over an entityframework datacontext (sql server).
I'm trying to get filtering to work. I've tried adding .UseFiltering() to a field descriptor like so...
descriptor.Field(t => t.AccountName).Type<NonNullType<StringType>>().UseFiltering();
But it causes this error on startup...
HotChocolate.SchemaException: 'Unable to infer or resolve a schema
type from the type reference Input: System.Char.'
I assume I'm doing something wrong somewhere...
"UseFiltering" is supposed to be used to filter data which represents a collection of items in some way (IQueryable, IEnumerable, etc).
For instance, if you have users collection and each user has AccountName property you could filter that collection by AccountName:
[ExtendObjectType(Name = "Query")]
public class UserQuery
{
[UseFiltering]
public async Task<IEnumerable<User>> GetUsers([Service]usersRepo)
{
IQueryable<User> users = usersRepo.GetUsersQueryable();
}
}
In that example the HotChocolate implementation of filtering will generate a number of filters by user fields which you can use in the following way:
users(where: {AND: [{accountName_starts_with: "Tech"}, {accountName_not_ends_with: "Test"}]})
According to your example: the system thinks that AccountName is a collection, so tries to build filtering across the chars the AccountName consists of.

Validate breeze save bundle before going to the breeze controller

Everywhere I look about validating the response before saving to the DB, in breeze, they are overriding the BeforeSaveEntity or BeforeSaveValidation.
e.g. breezejs issues with the save bundle. Is there anyway we can validate the savebundle before calling the saveChanges(), like in the repository level?
I want to pass the JObject savebundle from the controller to the relevant repository and do a few things there:
1) Check if the user has permission to save this entity
2) Do business-logic level validation
3) Do entity level operations such as updating the changedDate and changedUser, add default values to some other entity etc...
These are more like business-logic level operations and in our application we have like 20+ such entities that get saved from different parts of the application. If we override BeforeSaveEntity() we are doing all such business logic level validations for all entities inside the DataContext. Like
`if (entityInfo.Entity.GetType() == typeof(MyEntityTypeModel)) {
}`
I don't think if-else or case condition for 20+ entities is a good design. Besides, we have a clear separation of concerns through the use of repositories, so I think that's where this should be done.
How do we manipulate/validate the savebundle in such case?
Use the BeforeSaveEntities method ( documented here: http://www.getbreezenow.com/breeze-sharp-documentation/contextprovider). With this method you can work with ALL of the entities of a specified type without having to perform an 'if' test on each one.
Code might look something like this:
ContextProvider.BeforeSaveEntitiesDelegate = CheckFreightOnOrders;
return ContextProvider.SaveChanges(saveBundle);
private Dictionary<Type, List<EntityInfo>> CheckFreightOnOrders(Dictionary<Type, List<EntityInfo>> saveMap) {
List<EntityInfo> entityInfos;
// extract just those entities of type 'Order'
if (saveMap.TryGetValue(typeof(Order), out orderEntityInfos)) {
// then iterate over them.
foreach (var entityInfo in orderEntityInfos) {
CheckFreight(entityInfo);
}
}
return saveMap;
}

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
}
}

Entity Framework, mapping Views to Tables

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.

Resources