1

我首先在现有数据库、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 上下文提供程序来加入(许多)表并获取数据,因为每个表的实体不共享主键并且不从同一个类继承。

我认为这个 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);
});
};

我的角度:

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

我错过了什么吗?

4

2 回答 2

0

如扩展实体文档主题中所述,在 Breeze 客户端上非常简单:您在自定义构造函数中定义未映射的属性并注册该构造函数。

var metadataStore = myEntityManager.metadataStore;

metadataStore .registerEntityTypeCtor("Employee", Employee);

function Employee () 
  this.FooBar = ""; // unmapped property
};

现在 Breeze 元数据包括FooBar未映射属性的定义。服务器将向客户端发送一个值,Breeze 将在从查询中实现实体时FooBar填充该客户端Employee实体(未映射)属性。Employee

如何FooBar在服务器上获取该属性值取决于您。我对你的应用了解不够。您向我们展示的是一个完全有效的 Code First 实体定义。

也许您问的是实体框架问题而不是微风问题。

于 2013-11-16T06:45:36.367 回答
0

在CassidyK的这个 SO 答案中讨论了一种实现此功能的方法。这是代码片段。

 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 开发人员之一可以更好地解释。

似乎这只是为 Angular 配置 Breeze 时出现的问题。

IE

breeze.config.initializeAdapterInstance("modelLibrary", "backingStore", true);
于 2013-11-17T23:52:59.207 回答