2

我已经按照此处的教程创建了许多只读 Web Api OData 服务:http ://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api 。因此,我使用 ODataConventionModel 构建器从一组实体(顺便说一下来自 Telerik ORM)创建模型。这一切似乎都运行良好,我可以愉快地在服务上发出查询、查看元数据等。

我现在试图将注意力转移到其他 CRUD 操作上——首先是 Create 并偶然发现了一个问题!即,Post 方法正确触发(CreateEntity)但实体参数为空 - 通过对 ModelState.IsValid 进行检查,它表明问题是空 ID(键)值。这并不奇怪,因为数据库使用数据库生成的标识作为 ID 列,因此当实体保存到数据库上下文时会创建 ID。

因此,我尝试了各种将 ID 列标记为数据库生成的方法,但没有找到任何东西。奇怪的是,我似乎找不到任何人要求这个的帖子——当然我不能是唯一的一个?!

我注意到,在查看 EF 模型构建器时(例如这里:http ://forums.asp.net/t/1848984.aspx/1 )似乎有一种方法可以影响具有 .HasDatabaseGeneratedOption 属性的模型构建器,但是System.Web.Http.OData 等效项中不存在类似的选项。

因此,问题是:

  1. 有没有办法改变模型构建器(或其他东西),以便控制器接受对象并反序列化实体,即使键值为空?
  2. 如果是这样,我该怎么做?
  3. 如果没有,对其他选项有什么建议吗?

我意识到我可能只是用来自客户端请求的(在这种情况下)整数值填充对象,但这似乎 a)在语义上是错误的,并且 b)由于客户端工具包可能会导致不一定总是可能的使用。

感谢所有帮助!

非常感谢,

J。

4

2 回答 2

1

您需要为插入创建一个不包含 ID 参数的视图模型。使用 Automapper 将传入插入模型的属性映射到您的数据实体。

您遇到的问题是 ID 是数据模型中的必需属性,因为它是您的 PK,除了在插入期间不应指定它。

于 2013-06-25T21:05:11.337 回答
0

就我而言,我的数据库生成的密钥是一个 Guid。

作为一种解决方法,在我的 TypeScript 客户端代码中,我提交(通过 http POST)具有空 Guid 的对象,如下所示: 注意:ErrorId 是键列。

    let elmahEntry: ELMAH_Error = {
        Application: 'PTUnconvCost',
        Host: this.serviceConfig.url,
        Message: message,
        User: that.userService.currentUserEmail,
        AllXml: `<info><![CDATA[\r\n\r\n${JSON.stringify(info || {})}\r\n\r\n]]></info>`,
        Sequence: 1,
        Source: source,
        StatusCode: 0,
        TimeUtc: new Date(Date.now()),
        Type: '',
        ErrorId: '00000000-0000-0000-0000-000000000000'
    };

然后,在我的 WebApi OData 控制器中,我检查键是否为空 guid,如果是,我将其替换为新的 Guid,如下所示:

    // POST: odata/ELMAH_Error
    public IHttpActionResult Post(ELMAH_Error eLMAH_Error)
    {
        if (eLMAH_Error.ErrorId == Guid.Empty)
        {
            eLMAH_Error.ErrorId = Guid.NewGuid();
        }

        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        db.ELMAH_Error.Add(eLMAH_Error);

        try
        {
            db.SaveChanges();
        }
        catch (DbUpdateException)
        {
            if (ELMAH_ErrorExists(eLMAH_Error.ErrorId))
            {
                return Conflict();
            }
            else
            {
                throw;
            }
        }

        return Created(eLMAH_Error);
    }
于 2016-09-17T11:33:03.143 回答