I am using code first with an existing database, EF5, Web API and Breeze and I havent used any of these techs before. I am writing my own pocos.
I am trying to expose a read only property that requires several table joins to obtain the data. If we were using Web API only, we could just run some sql, populate the property and send some JSON back to the client.
Because we are using EF and breeze this obviously changes quite alot.
For example:
public class Employee
{
[Key]
public int EmployeeID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
[NotMapped]
public string FooBar
{
get { return getFooBar(); }
}
}
private string getFooBar()
{
// Do stuff here
}
This will send FooBar
back to the client in the JSON result but because it is not mapped, and consequently not in the Metadata, I dont seem to be able to use it within Breeze.
I have read articles that say I can do this when using designer based methods (ie edit the edmx file) but how can it be done using code first?
I am aware that I can extend a Breeze entity on the client side but Im not really sure how I would get this value which hasnt been mapped, after Breeze has created all of the entities.
What I really want is to extend my code first entity. I also vaguely understand that this might not be in line with EF ideals but I also struggle with the idea that I dont have the freedom to define what is and what isnt a property of my employee.
I dont need to track changes. I dont need to save. I dont seem to be able the use the EF context provider to join the (many) tables and get the data because the entities for each table dont share a primary key and dont inherit from the same class.
I think this SO post here suggests something similar but once again its for generated classes. Is there a way to do this? Thanks.
Edit
In reply to Wards suggestion I tried a few tests.
My client side constructor:
function Employee() {
this.DisplayName = ""; // unmapped property
};
My Controller:
function TestController($scope, $routeParams) {
var manager = new breeze.EntityManager('breeze/employees');
var metadataStore = manager.metadataStore;
metadataStore.registerEntityTypeCtor("Employee", Employee);
var query = new breeze.EntityQuery()
.from("Employees")
.orderBy("FirstName");
manager.executeQuery(query).then(function (data) {
// Check unmapped property name
var employeeType = metadataStore.getEntityType("Employee");
var unmapped = employeeType.unmappedProperties;
alert(unmapped[0].name) // Returns 'DisplayName'
alert(employeeType.dataProperties[3].name) // Returns 'DisplayName'
var prop = manager.metadataStore.getEntityType('Employee').getProperty('DisplayName');
alert(prop.name) // Returns 'DisplayName'
var first = data.results[0]
var fullName = first.DisplayName
alert(fullName) // Returns empty string
$scope.employees = data.results;
$scope.$apply();
}).fail(function (e) {
alert(e);
});
};
My Angular:
<div>
<ul>
<li data-ng-repeat="employee in employees">
{{employee.DisplayName}}
</li>
</ul>
</div>
So the property seems to be setup correctly as an unmapped property, but it only returns the empty string. If I change
this.DisplayName = ""; // unmapped property
to
this.DisplayName = "Foo"; // unmapped property
then DisplayName
always contains "Foo". The values from the payload are not being applied to DisplayName
.
Am I missing something?