Foreign Key Relationship to WebAPI Class

--- Decision ---

Thanks everyone for helping me, I was doing something wrong, I had two contexts because I didn't understand this concept, but now I have fixed it.

Here's what I changed based on your comments to make it work:

public class DatabaseContext : DbContext
{
    public DatabaseContext(DbContextOptions<DatabaseContext> options)
        : base(options)
    {
    }

    public DbSet<Grupo> Grupos { get; set; }
    public DbSet<Produto> Produtos { get; set; }

}

public class ProdutoRepository : IDefaultRepository<Produto>
{
    private readonly DatabaseContext _context;

    public ProdutoRepository(DatabaseContext context)
    {
        _context = context;

        if (_context.Produtos.Count() == 0)
            Add(new Produto { Nome = "Teste", GrupoId = 1 });
    }

    public IEnumerable<Produto> GetAll()
    {
        return _context.Produtos.Include(p => p.Grupo).ToList();
    }

    public void Add(Produto item)
    {
        _context.Produtos.Add(item);
        _context.SaveChanges();
    }

    public Produto Find(long key)
    {
        return _context.Produtos.Include("Grupo").FirstOrDefault(t => t.Id == key);
    }

    public void Remove(long key)
    {
        var entity = _context.Produtos.First(t => t.Id == key);
        _context.Produtos.Remove(entity);
        _context.SaveChanges();
    }

    public void Update(Produto item)
    {
        _context.Produtos.Update(item);
        _context.SaveChanges();
    }
}

public class GrupoRepository : IDefaultRepository<Grupo>
{
    private readonly DatabaseContext _context;

    public GrupoRepository(DatabaseContext context)
    {
        _context = context;

        if (_context.Grupos.Count() == 0)
            Add(new Grupo { Nome = "Teste" });
    }

    public IEnumerable<Grupo> GetAll()
    {
        return _context.Grupos.ToList();
    }

    public void Add(Grupo item)
    {
        _context.Grupos.Add(item);
        _context.SaveChanges();
    }

    public Grupo Find(long key)
    {
        return _context.Grupos.FirstOrDefault(t => t.Id == key);
    }

    public void Remove(long key)
    {
        var entity = _context.Grupos.First(t => t.Id == key);
        _context.Grupos.Remove(entity);
        _context.SaveChanges();
    }

    public void Update(Grupo item)
    {
        _context.Grupos.Update(item);
        _context.SaveChanges();
    }
}

      

---/Decision ---

--- EDIT # 4 ---

I don't know if I should indicate that I want it to be automatic, if I put an FK, I want to point it to an object so that it will cast it to JSON without manually creating it.

--- / EDIT # 4 ---

--- EDIT # 3 ---

Ok, so I couldn't solve it, so I put the code on GitHub so you can take a look, this is just a test project, so no problem, it's a small project.

https://github.com/heronz/LysiSolutionNumber01

--- / EDIT # 3 ---

I am new to C # and WebAPI development and I am trying to find out how to make communication between two objects using a foreign key and when for endpoint access I would like it to bring something like this:

{
    productId:1,
    productName:"Test",
    productGroupId:1
    productGroup:{
        groupId:1,
        groupName:"Test Group"
    }
}

      

But I am getting something like this:

{
    productId:1,
    productName:"Test",
    productGroupId:1
    productGroup:null
}

      

In my classes I already use annotations like this

public class Product
{        
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public long productId{ get; set; }
    public string productName{ get; set; }

    [ForeignKey("group")]
    public long productGroupId{ get; set; }        
    public virtual Group productGroup{ get; set; }
}

public class Group
{        
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public long groupId{ get; set; }
    public string groupName{ get; set; }
}

      

And I am using the repository / context as described in this tutorial

https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-web-api

When I start my repository, I use it like this:

public ProductRepository(ProductContext context)
{
    _context = context;

    if (_context.Reg.Count() == 0)
        Add(new Product{ productName = "Test", productGroupId= 1 });
}

      

I tried looking for how to do this, found something about DTOs, but I didn't get it, so maybe that's what it is.

I am involved in the learning process, so there is no ready-made application just something that I create based on the tutorial I mentioned above.

--- EDIT ---

As pointed out in the comments, here's the GET method.

public IEnumerable<Product> GetAll()
{
    return _context.Reg.ToList();
}

public Produto Find(long key)
{
    return _context.Reg.FirstOrDefault(t => t.Codigo == key);
}

      

This is the context (edited):

public class ProductContext : DbContext
{
    public ProductContext(DbContextOptions<ProductContext> options)
        : base(options)
    {
    }

    public DbSet<Product> Reg { get; set; }

}

      

--- EDIT # 2 ---

Tried adding a link to products in a group

public class Group
{        
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public long groupId{ get; set; }
    public string groupName{ get; set; }
    public virtual ICollection<Product> Products{ get; set; }
} 

      

And in the GET methods added the included thing

public IEnumerable<Product> GetAll()
{
    return _context.Reg.Include(p => p.productGroup).ToList();
}

public Produto Find(long key)
{
    return _context.Reg.Include(p => p.productGroup).FirstOrDefault(t => t.Codigo == key);
}

      

Still not working, maybe there is something I am referencing the group with here?

public ProductRepository(ProductContext context)
{
    _context = context;

    if (_context.Reg.Count() == 0)
        Add(new Product{ productName = "Test", productGroupId= 1 });
}

      

Because this way I am only referring to FK, maybe I need to refer to an object? But how?

+3


source to share


2 answers


You will need to make some changes:




ProductContext

Add the following line

public DbSet<Group> Group { get; set; }

      




Classe product

Remove next property

public long productGroupId { get; set; }

      

The system already recognizes FK and creates a field in the database.




The class into which you insert the new product

This is where you get the group from the database (if the group is already registered)

var group = _context.Group.Find(1);

      

Create a new product collection if it is null.

if (group.Products == null)
    group.Products = new List<Product>();

      

And then you add to the list of products for the selected group.

 group.Products.Add(new Product { productName = "Test" });

      




Stay like this:

public ProductRepository(ProductContext context)
{
    _context = context;
    var group = _context.Group.Find(1);

    if (group.Products == null)
        group.Products = new List<Product>();

    if (_context.Reg.Count() == 0)
       group.Products.Add(new Product { productName = "Test" });
}

      

+1


source


I completely missed that this is a .NET core without a database. This is why I have updated my entire answer.

After all the updates in the question, there are some things I noticed.

1) You use all types of names for tables and fields. This is confusing and difficult to answer. If the foreign key is matched by name, the name must be known. If the Products table is named Reg, what is the name of the table group? If this is not the case for ProductGroup, this could be a problem.

2) Where is the Group table in the DbContext? Update the context including ProductGroup.

3) In the bootstrap repository, you add one product, but I don't see that the group has been added. Can you confirm that the ProductGroup table exists and has at least one record with IDs Id = 1 and name = "Test Group"?



What does not change, this includes ProductGroup:

var product = context.Products.Include("ProductGroup").FirstOrDefault(p => p.Id == id);

      

This should return the Product including ProductGroup. As for the attribute [ForeignKey("group")]

in the product class. This should be "ProductGroupId", not "group". But if the table names are "Products" and "ProductGroup", you can delete them. By convention, ProductGroupId is a foreign key to ProductGroup.

Seated, you can use the top CamelCase for the field names. Set the parameter in json serializer to convert to lower camelCase.

Due to the above problems, it is difficult to answer. It may be that the group has no records, the tables have different names than expected, or the attributes are invalid. Perhaps you can solve the problem with what I already mentioned. Otherwise, please update your question.

0


source







All Articles