Is there a way to map properties to column names using some .Insert extension method for Dapper? - dapper

I have the following challenge with this class:
Public Class MyClass
Property Id As Integer
Property LastName as String
End Class
The corresponding data table in the database has as fields:
Id (int, not null)
Last-Name (nvarchar(80),null)
So I need to map MyClass.LastName to MyClasses.Last-Name and have a hell of a time...
When I write a custom Insert query it all works, but I would like to use the .Insert statement of one of the Dapper extensions packages.
I tried Dapper.Contrib, but this ignores mappings that I create using Dapper.FluentMap or using the built in method of Dapper itself using Dapper.SetTypeMap.
I tried Dapper.FastCrud, but I was unable to figure out how to configure mappings for it, though this API seems promising.
Anyone?

So, basically the problem here is that the property name and column name is different.
With Dapper, you can handle this by providing alias for column name in SQL query. I guess you have already tried this as you said "I write a custom Insert query" in your question. Other multiple ways to map column names with properties are discussed here.
With DapperExtensions, you can map the different column names with their respective properties something like below:
public sealed class MyClassMapper : ClassMapper<MyClass>
{
public MyClassMapper()
{
Table("MyTable");
Map(x => x.Id).Key(KeyType.WhatYouWant);
Map(x => x.LastName).Column("Last-Name");
AutoMap();
}
}
Code sample is with C#. You have to translate it to VB.NET.
With Dapper.Contrib, you can decorate the class with [Table] attribute to map the table name. Alternatively, you can use SqlMapperExtensions.TableNameMapper to map the tables. Please refer to this blog post or this and this and this SO posts for more details.
Apparently, there is no way to map the column name. This feature is planned for next major (2.x) version. Version 2.x is released; but the issue is still open. Looking at the release notes, feature is not yet added.
With Dapper.FastCrud, there are multiple ways for mapping. You can decorate the property with [Column] attribute.

Related

Using UUID for id on Pages

Just getting started with Wagtail. To support interoperability with a legacy system, I'd like to have the id/pk of my Page objects be UUIDs instead of Integers. I tried just adding a id = models.UUIDField(primary_key=True, editable=False, default=uuid.uuid4) to my class that inherits from Page but I get an error Local field u'id' clashes with field of similar name from base class 'Page'
Is there a simple way to make id be a UUID? Or, do I just need to call it something besides id?
There won't be a simple way to do this, unfortunately - the assumption that IDs are numeric is baked in to the database schema, URL routes, rich text data representation and various other places in Wagtail's design.
Would it be an option to add your UUID column as a new field on your model (named something like legacy_id), and look up on that whenever you need to interoperate with the legacy system - but otherwise leave the primary key as numeric?

ASP.net Web API - Example pre-existing database Fluent NHibernate and Automapper

I am working through the ASP.net Web API 2 book (Git Hub)
I am trying to use Fluent NHibernate and Automapper to connect to a database. The book uses a fresh database while my database is pre-existing and not necessarily controlled by good practices.
Before joining tables etc. I would like to just be able to get a list of people and add a new person via the API. The only catch is that I would like to return less properties of the actual table and create a new person with even less than the model used to display a new person. I am having trouble understanding the flow of the automapper.
An example table might be
<pre>Person Entity
-person_id(int)
-person_name(varchar(100))
-person_location(int)
-person_phone(varchar(10))
-person_address(varchar(30))
</pre>
The model I want to use includes a subset of the items in the actual table. For example, maybe:
<pre>Person Model
-person_id(int)
-person_name(varchar(100)
-person_location(int)</pre>
There is also a newPerson model
<pre>NewPerson Model
-Name
-location</pre>
I have an Entity with all the person properties like
public virtual int person_id {get;set;}
but I have a model with the subset properties like
public long person_id {get; set;}
In the automapping configuration file I have a class NewPersonToPersonEntityAutoMapperTypeConfigurator and I have another class PersonEntityToPersonAutoMapperTypeConfigurator
I'm confused about how automapper is working. Should the AutoMapper file NewPersonToPersonEntityAutoMapperTypeConfigurator use something like
Mapper.CreateMap<NewPerson, PersonEntity>
.ForMember(opt => opt.person_id, x => x.Ignore())
...
.ForMember(opt => opt.person_address(varchar(30)))
While
PersonEntityToPersonAutoMapperTypeConfigurator uses something like
Mapper.CreateMap<PersonEntity, PersonModel>
Can anyone show me a good example of a simple scenario like this with automapper and a pre-existing table with extra unused properties or describe what Automapper should be doing or if I am on the right track?
Daniel - I think you're on the right track. Yes, you need an AutoMapper map for each "direction"... i.e. incoming service message to the EF entity, and from the EF entity to the service return message.
Your code to ignore certain properties is fine. You just need to make sure the entity is populated appropriately for the INSERT into the database. For example, the person_id column - is that required to be set? Or is that an auto-incrementing column??
To say it another way... you can certainly use AutoMapper (and our approach in the book) against an existing database. It's still just mapping properties from one type to another type.
Feel free to send some code my way.

Do Fluent conventions break lazy loading? (uNhAddIns)

I have a simple entity class in a WPF application that essentially looks like this:
public class Customer : MyBaseEntityClass
{
private IList<Order> _Orders;
public virtual IList<Order> Orders
{
get { return this._Orders; }
set {this._Orders = new ObservableCollection<Order>(value);}
}
}
I'm also using the Fluent automapper in an offline utility to create an NHibernate config file which is then loaded at runtime. This all works fine but there's an obvious performance hit due to the fact that I'm not passing the original collection back to NHibernate, so I'm trying to add a convention to get NHibernate to create the collection for me:
public class ObservableListConvention : ICollectionConvention
{
public void Apply(ICollectionInstance instance)
{
Type collectionType =
typeof(uNhAddIns.WPF.Collections.Types.ObservableListType<>)
.MakeGenericType(instance.ChildType);
instance.CollectionType(collectionType);
}
}
As you can see I'm using one of the uNhAddIns collections which I understand is supposed to provide support for both the convention and INotification changes, but for some reason doing this seems to break lazy-loading. If I load a custom record like this...
var result = this.Session.Get<Customer>(id);
...then the Orders field does get assigned an instance of type PersistentObservableGenericList but its EntityId and EntityName fields are null, and attempting to expand the orders results in the dreaded "illegal access to loading collection" message.
Can anyone tell me what I'm doing wrong and/or what I need to do to get this to work? Am I correct is assuming that the original proxy object (which normally contains the Customer ID needed to lazy-load the Orders member) is being replaced by the uNhAddIns collection item which isn't tracking the correct object?
UPDATE: I have created a test project demonstrating this issue, it doesn't reference the uNhAddins project directly but the collection classes have been added manually. It should be pretty straightforward how it works but basically it creates a database from the domain, adds a record with a child list and then tries to load it back into another session using the collection class as the implementation for the child list. An assert is thrown due to lazy-loading failing.
I FINALLY figured out the answer to this myself...the problem was due to my use of ObservableListType. In NHibernate semantics a list is an ordered collection of entities, if you want to use something for IList then you want an unordered collection i.e. a Bag.
The Eureka moment for me came after reading the answer to another StackOverflow question about this topic.

Entity Framework Migrations - Change Property DataType

I am developing an ASP.Net MVC 4 web application with Entity Framework 5.0 for data persistence. I am using Code First and Automatic Migrations during development.
As I had to work with an existing database I used this helpful tutorial to create my Domain Classes
Code First to an Existing Database
I have a class in my model named tblcourseapplicant which has a String property called ManagerTitle. I would like to change this datatype to Int, and to do this I changed the property in the POCO class
from
public string ManagerTitle { get; set; }
to
public int ManagerTitle { get; set; }
and then I changed the property attribute in the relevant Mapping Class (tblcourseapplicantMap) using Fluent API
from
this.Property(t => t.ManagerTitle).HasMaxLength(5);
to
this.Property(t => t.ManagerTitle).IsRequired();
I also updated all the data in the database for this particular column so that all the values were converted to integers.
I ran my project and the automatic migrations try to perform this update for me, but it comes back with the following error
Cannot insert the value NULL into column 'ManagerTitle', table
'tblcourseapplicant'; column does not allow nulls. UPDATE fails. The
statement has been terminated.
I can't understand why this is, as there are no records in my database table where ManagerTitle is NULL, they have all been assigned an integer value.
Any help would be greatly appreciated.
Thanks.
UPDATE
Folks I am still struggling to find a solution to this problem. I noticed that the error coming back is an SqlException. Does anyone have any ideas please? I don't understand what the problem is here, my understanding is that Code First Automatic Migrations should be able to handle this simple property datatype change.
Help!
Has the column been defined as nullable in the database?
You can also try making it nullable in the POCO
public int? ManagerTitle { get; set; }
When doing a similar update with non-Automatic Migrations the update code would just delete the old column and create a new one without any data migration between renamed (or retyped) properties.
I suspect this might be the case with your issue.

Silverlight / .NET RIA Services - Exposing a custom property to the client

I have a table in my database called "Task". Task has the following fields:
- ID
- Description
- AssignedUserID
- TaskTypeID
I am accessing this table through a class that was created automatically after I used an ADO.NET Entity Data Model. I can load and show the fields mentioned above in a DataGrid in my Silverlight application. However, AssignedUserID and TaskTypeID are not very descriptive. So I decided to create a stored procedure that gets the tasks and the user and task type names through their respective lookup tables. This is where the problem lies.
I want to create some custom properties in the automatically generated "Task" class. The custom properties would be named "AssignedUserName" and "TaskType". I then want to make these properties available to my Silverlight client. However, I cannot seem to figure out how to get them exposed to my Silverlight client.
Can someone help?
Thank you
If your EDM is in the same project as the DomainService you can do this:
create a partial class on the Entity type, and add your calculated property in there.
name the file **.shared.cs
it will then be auto-shared with the client/Silverlight code.
Edit:
I was assuming that you could do this calculation in app logic rather than use an sp, which seems more straightforward to me.
If you do use an SP, you'll need to use the Function Import feature in the designer to map the SP to a function in the EDM. This function can then return entities, with properties mapped however you like.
An easier way would be to just use the object model: Have Task.AssignedUser and Task.TaskType objects off of your Task class. Map these to lookup tables in your db. This will work out-of-the box (assuming the Id's are FK's to those lookup tables).
So, a couple options:
use app-logic--properties in a partial class to return the descriptions
use the object model driven by FKs to lookup tables, then just access Task.AssignedUser.Name or Task.TaskType.Description
use a function import to access the SP and map the returned values to entity properties
1 or 2 being the best options IMHO.
Another approach might be to update your EF model to include the lookup tables, add Associations between the tables, add [Include]s in the (auto-gen'd) metadata class and let EF and RIA do it for you. Maybe.

Resources