How to create and update a relation between documents in DocumentDB using ASP.NET Web API

穿精又带淫゛_ 提交于 2020-01-14 05:22:13

问题


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; }
    }

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": [ ]
}

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"
}

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]
}

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();
    }

...

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.


回答1:


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

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

  • 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)

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

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

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.



来源:https://stackoverflow.com/questions/29997490/how-to-create-and-update-a-relation-between-documents-in-documentdb-using-asp-ne

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!