如何使用ASP.NET Web API在DocumentDB中创建和更新文档之间的关系 [英] How to create and update a relation between documents in DocumentDB using ASP.NET Web API

查看:60
本文介绍了如何使用ASP.NET Web API在DocumentDB中创建和更新文档之间的关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是.NET和Azure的新手,并且正在尝试创建一个简单的Web API,以帮助我学习.我有两个DocumentDB文档集合.每个集合中的文档定义如下:

I am new to .NET and Azure, and am trying to create a simple Web API, to help me learn. I have two collections of DocumentDB documents. The documents in each collection are defined as follows:

public class Log
    {
        [JsonProperty(PropertyName = "id")]
        public string Id { get; set; }

        [JsonProperty(PropertyName = "studentName")]
        public string StudentName { get; set; }

        [JsonProperty(PropertyName = "assignment")]
        public string Assignment { get; set; }


        [JsonProperty(PropertyName = "dueDate")]
        public DateTime DueDate { get; set; }

        [JsonProperty(PropertyName = "goal")]
        public string Goal { get; set; }

        [JsonProperty(PropertyName = "reflection")]
        public string Reflection { get; set; }

        [JsonProperty(PropertyName = "sessions")]
        public List<Session> Sessions { get; set; }
    }

    public class Session
    {
        [JsonProperty(PropertyName = "id")]
        public string Id { get; set; }

        [JsonProperty(PropertyName = "date")]
        public DateTime Date { get; set; }

        [JsonProperty(PropertyName = "duration")]
        public TimeSpan Duration { get; set; }

        [JsonProperty(PropertyName = "comment")]
        public string Comment { get; set; }
    }

以下是我对Log文档所拥有的一个示例:

Here is an example of what I have for the Log documents:

{
    "id": "2",
    "studentName": "Joe student",
    "assignment": "Web APIs",
    "dueDate": "0001-01-01T00:00:00",
    "goal": "Keep mistakes to a minimum.",
    "reflection": "I'm getting there.",
    "sessions": [ ]
}

以下是我对Session文档的了解示例:

Here is an example of what I have for the Session documents:

{
    "id": "7",
    "date": "2015-04-26T00:00:00",
    "duration": "00:30:00",
    "comment": "Practiced for 30 minutes"
}

我想将会话"与日志"相关联,以便每个日志"可以有多个会话,但是每个会话都将与一个日志"以及一个学生"相关.我想我希望将这些会话作为单独的文档,因为我可能想按学生"或日志"获取会话列表.也将有学生文件. 我正在努力将会话添加到日志中,而不是简单地在日志中复制会话.我想得到这样的东西,其中列出了相关会话的ID:

I would like to relate Sessions with Logs such that each Log may have several sessions, but each session will be related to a single Log, and also a single Student. I think I want the sessions as separate documents, because I may want to get a list of Sessions by either Student, or Log. There would be Student documents as well. I am struggling to add Sessions to a Log, without simply duplicating the session within the log. I would Like to get something like this, which lists the id's of related sessions:

{
    "id": "2",
    "studentName": "Joe student",
    "assignment": "Web APIs",
    "dueDate": "0001-01-01T00:00:00",
    "goal": "Keep mistakes to a minimum.",
    "reflection": "I'm getting there.",
    "sessions": [1, 2, 7, 19, 22]
}

然后我想通过用实际文档的内容替换id来显示日志.

I would then like to display the log, by replacing the ids with the content of the actual documents.

以下是一些相关的工作代码段(不一定正确),向您展示我的设计结构:

Here are some related working code snippets ( Not necessarily correct) to show you my design structure:

public class PracticeLogRepository : DocumentDB
{
    // ********** Logs section ********** //
    private PracticeSessionRepository _sessionsRepository;

    // specifies the database and document collection used by the repository
    public PracticeLogRepository() : base("Project3", "Logs") { }

    // Gets a  list of practice Logs
    public Task<List<Practice.Log>> GetLogsAsync()
    {
        return Task<List<Practice.Log>>.Run(() => Client
            .CreateDocumentQuery<Practice.Log>(Collection.DocumentsLink)
            .ToList());
    }

    // Gets the practice Log with the matching id
    public Task<Practice.Log> GetLogAsync(string id)
    {
        return Task<Practice.Log>.Run(() => Client
            .CreateDocumentQuery<Practice.Log>(Collection.DocumentsLink)
            .Where(pl => pl.Id == id)
            .AsEnumerable()
            .FirstOrDefault());
    }

...

public class PracticeSessionRepository : DocumentDB
{
    // ********** Session section ********** //

    // specifies the database and document collection used by the repository
    public PracticeSessionRepository() : base("Project3", "Sessions") { }

    // Gets a  list of practice Sessions
    public Task<List<Practice.Session>> GetSessionsAsync()
    {
        return Task<List<Practice.Session>>.Run(() => Client
            .CreateDocumentQuery<Practice.Session>(Collection.DocumentsLink)
            .ToList());
    }

    // Gets the practice Log with the matching id
    public Task<Practice.Session> GetSessionAsync(string id)
    {
        return Task<Practice.Session>.Run(() => Client
            .CreateDocumentQuery<Practice.Session>(Collection.DocumentsLink)
            .Where(pl => pl.Id == id)
            .AsEnumerable()
            .FirstOrDefault());
    }

...

public class LogController : ApiController
{
    private PracticeLogRepository _logsRepository;

    public LogController()
    {
        _logsRepository = new PracticeLogRepository();
    }

    // GET: api/Log
    public async Task<IHttpActionResult> Get()
    {
        var logs = await _logsRepository.GetLogsAsync();
        if (logs != null)
            return Ok(logs);
        return NotFound();
    }

    // Get: api/Log/{id}
    public async Task<IHttpActionResult> Get(string id)
    {
        var log = await _logsRepository.GetLogAsync(id);
        if (log != null)
            return Ok(log);
        return NotFound();
    }

...

public class SessionController : ApiController
{
    private PracticeSessionRepository _sessionsRepository;

    public SessionController()
    {
        _sessionsRepository = new PracticeSessionRepository();
        //_logsRepository = new PracticeLogRepository();
    }

    // GET: api/Session
    public async Task<IHttpActionResult> Get()
    {
        var sessions = await _sessionsRepository.GetSessionsAsync();
        if (sessions != null)
            return Ok(sessions);
        return NotFound();
    }

    // Get: api/Session/{id}
    public async Task<IHttpActionResult> Get(string id)
    {
        var session = await _sessionsRepository.GetSessionAsync(id);
        if (session != null)
            return Ok(session);
        return NotFound();
    }

...

由于我正在自学,并且是全新的.NET和C#,当然还有DocumentDB,所以我一直在努力编写此代码.我将非常欣赏一个简单的示例,该示例说明了如何创建Log文档以及如何通过添加会话来更新它.

Since I am teaching myself, and am extremely new .NET and C#, and of course DocumentDB, I am struggling to code this. I would really appreciate a simple example of how I should create the Log document, and also how to update it by adding sessions.

如果您需要查看更多我的代码,只需询问.我只是不想太复杂.

If you need to see more of my code, just ask. I just don't want to over complicate this.

推荐答案

我想确保我了解这个问题,以下是对我的理解的总结:

I'd like to make sure I'm understanding the question, here's a recap of my understanding:

  • 您在Log和Session之间具有一对多的关系.

  • You have a 1-to-many relationship between Log and Session.

Log和Student之间具有一对一的关系.

You have a 1-to-1 relationship between Log and Student.

您想按学生"或日志"查询会话.

You'd like to query Sessions by either Student or Log.

您想从这些关系中填充数据(例如获取会话数据)

You'd like to populate data from these relationships (e.g. get the session data)

请记住,DocumentDB是一个NoSQL数据库,不支持文档间的JOIN.

Please keep in mind DocumentDB is a NoSQL database and does not support inter-document JOINs.

我建议您重新研究如何对数据建模,特别是如何表示关系(例如,是否将会话"和日志"保留为单独的文档).

I'd recommend revisiting how you approach modeling your data - in particular how you represent relationships (e.g. whether to keep Sessions and Logs as separate documents).

以下文章详细讨论了对数据建模的问题: http://azure.microsoft.com/en-us/documentation/articles/documentdb-modeling-data/

The following article talks about modeling data in detail: http://azure.microsoft.com/en-us/documentation/articles/documentdb-modeling-data/

总结一下本文的要点-我将在应用程序的规范化(例如,将Sessions和Logs保留为单独的文档)和取消规范化(例如,将Sessions和Logs保留在同一文档中)之间进行适当的权衡.用例.通常,当您有大量读取应用程序时,我更喜欢取消规范化;而对于有大量写入应用程序,则我更喜欢进行规范化.

To summarize the key points of the article - I would pick the appropriate trade-off between normalizing (e.g. keeping Sessions and Logs as separate documents) and de-normalizing (e.g. keeping Sessions and Logs in the same document) given your application's use case. In general, I prefer de-normalizing when you have a read-heavy application and normalizing when you have a write-heavy application.

如果您选择标准化-您只需提出后续请求即可获取日志的会话数据. 额外的信用:您甚至可以更进一步,并且无需通过编写存储过程来发出多个网络请求.

If you choose to normalize - you can simply make a follow-up request to get the session data for a log. Extra credit: You can even take this a step further and remove the need of having to make multiple network requests by writing a stored procedure.

如果选择取消规范化,则只需查询整个文档,所有内容都会自动填充.缺点是,如果更新会话数据,您可能必须扇出对多个文档的写入.

If you choose to de-normalize, you can simply query for the entire document and everything will be populated automatically. The drawback is you may have to fan-out writes to multiple documents if you update session data.

这篇关于如何使用ASP.NET Web API在DocumentDB中创建和更新文档之间的关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆