简体   繁体   中英

EF Core navigation properties loads itself

I have the folllowing classes as entities in my DB_Context.

public class Glossary
{
    #region Properties
    public Guid GlossaryId { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }


    #region NavigationProperties
    public virtual ICollection<Item> Items { get; set; }
    #endregion
}
public class Item
{
    #region Properties
    public Guid ItemId { get; set; }
    public string Name { get; set; }
    public string Definition { get; set; }

    #region ForeignKeys
    public Guid GlossaryId { get; set; }
    #endregion
    #endregion

    #region Navigation Properties
    public virtual Glossary Glossary { get; set; }
    #endregion
}

When I try to include the Items of an entity of type Glossary using

public async Task<IEnumerable<Glossary>> Get()
    {
        return await _context.Glossaries
                    .Include(x => x.Items)
                    .OrderBy(x => x.CreatedAt)
                    .ToListAsync();
    }

I get the Following JSOn from my API:

{
    "glossaryId": "674c1358-861b-11ea-9370-e45a1762a61b",
    "name": "Test1",
    "description": "Description of Test1",
    "items": [
        {
            "itemId": "f2847601-86db-11ea-9370-e45a1762a61b",
            "name": "TestItem",
            "definition": "TestDefinition",
            "glossaryId": "674c1358-861b-11ea-9370-e45a1762a61b",
            "glossary": {
                "glossaryId": "674c1358-861b-11ea-9370-e45a1762a61b",
                "name": "Test1",
                "description": "Description of Test1",
                "items": []
            }
        }
    ]
}

My Problem is, that the Item of the Glossary includes it's Glossary as well, which I don't want.

Any way to only include the one navigation property without including the same again?

In order to avoid this issue, in every project, I always use DTOs and Automapper. Usually, it's never necessary to give back the database model as it is: give just what you need to solve the functionality. In your case you need to give back all Glossaries.

In your situation I would introduce Automapper. After installingAutomapper on your Net.Core project, I would create 2 DTOs called:

public class GlossaryDto : ICustomMapping

    public Guid GlossaryId { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }      

    public ICollection<ItemDto> Items { get; set; }

    public void CreateMappings(Profile configuration)
    {
        configuration.CreateMap<Glossary, GlossaryDto>();
    }

public class ItemDto  : ICustomMapping
{
    public Guid ItemId { get; set; }
    public string Name { get; set; }
    public string Definition { get; set; }

    public Guid GlossaryId { get; set; }

    public void CreateMappings(Profile configuration)
    {
        configuration.CreateMap<Item, ItemDto>();
    }

}

Now you can simply rewrite your Get in order to give back the Dto instead of the database model (entity):

public async Task<IEnumerable<GlossaryDto>> Get()
    {
        var result = await _context.Glossaries
                    .Include(x => x.Items)
                    .OrderBy(x => x.CreatedAt)
                    .ToListAsync()
        return await mapper.Map<IEnumerable<GlossaryDto>(result);
    }

In this way we removed the circular reference from the Dto and you would not have any problem: since ItemDto has no "navigation" property to GlossaryDto the chain has been correctly closed. Your JSON has all necessary information. In the future if you need to give back and ItemDto with a GlossaryDto navigation property, create a new one with a different name. You could also create a DTO equals to the database Model and then "cut" the circular references with automapper by specifying MaxDepth() , but I prefer to create specific DTOs for what's really needed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM