我首先使用现有数据库,EF5,Web API和Breeze的代码,之前我还没有使用过这些技术。我正在写自己的pocos。
我试图公开一个只读属性,需要多个表连接才能获取数据。如果我们只使用Web API,我们可以运行一些sql,填充属性并将一些JSON发送回客户端。
因为我们正在使用EF和微风这显然会发生很大变化。
例如:
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
}
这会将FooBar
发送回JSON结果中的客户端,但因为它没有映射,因此不在元数据中,所以我似乎无法在Breeze中使用它。
我读过一些文章,说我可以在使用基于设计器的方法(即编辑edmx文件)时执行此操作,但如何首先使用代码完成?
我知道我可以在客户端扩展Breeze实体但是我不确定在Breeze创建了所有实体之后我将如何获得未映射的值。
我真正想要的是扩展我的代码第一个实体。我也模糊地理解这可能不符合EF理想,但我也很难理解我没有自由来定义什么是什么,什么不是我的员工的财产。
我不需要跟踪更改。我不需要保存。我似乎无法使用EF上下文提供程序加入(很多)表并获取数据,因为每个表的实体不共享主键而不从同一个类继承。
我认为this SO post here表示类似的东西,但它再一次表示生成的类。有没有办法做到这一点?感谢。
修改
在回答Wards的建议时,我尝试了一些测试。
我的客户端构造函数:
function Employee() {
this.DisplayName = ""; // unmapped property
};
我的控制器:
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>
因此该属性似乎被正确设置为未映射的属性,但它只返回空字符串。如果我改变
this.DisplayName = ""; // unmapped property
到
this.DisplayName = "Foo"; // unmapped property
然后DisplayName
总是包含“Foo”。有效负载中的值未应用于DisplayName
。
我错过了什么吗?
答案 0 :(得分:0)
在Extending Entities文档主题中解释的Breeze客户端非常简单:在自定义构造函数中定义一个未映射的属性并注册该构造函数。
var metadataStore = myEntityManager.metadataStore;
metadataStore .registerEntityTypeCtor("Employee", Employee);
function Employee ()
this.FooBar = ""; // unmapped property
};
现在,Breeze元数据包含FooBar
未映射属性的定义。服务器将向客户端发送FooBar
的值,当Breeze从查询中实现Employee
个实体时,它将填充该客户端Employee
实体(未映射)属性。
如何获取服务器上的FooBar
属性值取决于您。我对你的应用程序知之甚少。您向我们展示的是完全有效的Code First实体定义。
也许你问的是实体框架问题而不是微风问题。
答案 1 :(得分:0)
CassidyK讨论了in this SO answer的一种方法。这是代码片段。
proto.initializeFrom = function (rawEntity) {
// HACK:
// copy unmapped properties from newly created client entity to the rawEntity.
// This is so that we don't lose them when we update from the rawEntity to the target.
// Something that will occur immediately after this method completes.
var that = this;
this.entityType.unmappedProperties.forEach(function(prop) {
var propName = prop.name;
that[propName] = rawEntity[propName]; // CassidyK
//rawEntity[propName] = that[propName]; // Breeze
});
if (!this._backingStore) {
this._backingStore = { };
}
};
我不知道这是什么副作用。也许其中一个Breeze开发者可以更好地解释。
当Breeze配置为Angular时,这似乎只是一个问题。
IE
breeze.config.initializeAdapterInstance("modelLibrary", "backingStore", true);