Returning multiple joined/navigation objects - c#

I recently inherited an ASP.NET Entity Framework API project.
I managed to do basic changes that were needed, but I'm getting a little lost with advanced SQL requests (I'm more a Symfony dev, I don't know Entity Framework).
I need to add a GET method to my API that will take a service (prestation) and will return a list of all the partners (Partenaires) who has a service (Prestation) with the same name as the GET parameter.
Here's the actual prototype of the method:
// GET: api/Partenaires_prestations
[Authorize]
public List<PartenaireMapItem> GetPartenairesWithPrestations(string prestation = "")
{
if (string.IsNullOrWhiteSpace(prestation))
{
prestation = "";
}
return db.Partenaires
.Join() // Here I don't know what to do
}
I have 3 tables that I have to use:
Prestation, Partenaires, PartenairesPrestation
Here are the 3 tables classes:
namespace Uphair.EfModel
{
using System;
using System.Collections.Generic;
public partial class Partenaire
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Partenaire()
{
this.PartenairePrestations = new HashSet<PartenairePrestation>(); // I took out the useless parts
}
public int IdPartenaire { get; set; }
[...] // I took out properties that are not needed
public virtual ICollection<PartenairePrestation> PartenairePrestations { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
}
namespace Uphair.EfModel
{
using System;
using System.Collections.Generic;
public partial class PartenairePrestation
{
public int IdPartenaire { get; set; }
public int IdPrestation { get; set; }
public double Prix { get; set; }
public int Duree { get; set; }
public Nullable<System.DateTime> DateAjout { get; set; }
public virtual Partenaire Partenaire { get; set; }
public virtual Prestation Prestation { get; set; }
}
}
namespace Uphair.EfModel
{
using System;
using System.Collections.Generic;
public partial class Prestation
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Prestation()
{
this.PartenairePrestations = new HashSet<PartenairePrestation>();
this.PrixDureeOptions = new HashSet<PrixDureeOption>();
this.LigneReservations = new HashSet<LigneReservation>();
}
public int IdPrestation { get; set; }
public string NomPrestation { get; set; }
public int Categorie { get; set; }
public Nullable<int> CoifEsthe { get; set; }
public Nullable<int> IdPrestationCategorie { get; set; }
public virtual ICollection<PartenairePrestation> PartenairePrestations { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
}
The last one makes the link between Partenaires and Prestation via IdPartenaire and IdPrestation columns.
Here's a screenshot of my model structure:
https://imageshack.com/a/img922/9111/4twiC8.png (imgur is not responding sorry)
Here's the PartenaireMapItem model:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Uphair.EfModel;
namespace Uphair.Api.Models.Partenaire
{
public class PartenaireMapItem
{
public int IdPartenaire { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string NomComplet { get; set; }
public double? Lat { get; set; }
public double? Lng { get; set; }
public PartenaireType Type { get; set; }
public int DureeMin { get; set; }
public string ImageUrl { get; set; }
public int SeDeplace { get; set; }
public bool ADomicile { get; set; }
public double NoteGlobale { get; set; }
public List<String> Prestations { get; set; }
}
}
I need to use join to get a list of partners (Partenaires) that have the service (Prestation) with the service name provided in the GET parameter, but I don't know how to do it.
Any help would be welcome, thanks to anyone who will take the time to read/answer me.

Related

The property 'DadosRequisicao.CnpjFornecedor' could not be mapped because it is of type 'List<string>'

I'm trying to do the migration from my properties on Models, and is returning this message:
The property 'DadosRequisicao.CnpjFornecedor' could not be mapped because it is of type 'List<string>', which is not a supported primitive type or a valid entity type. Either explicitly map this property, or ignore it using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.
My code:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace PortalDeCotacao.Models
{
public class DadosRequisicao
{
[Key]
[Required]
public int Id { get; set; }
public string DataLimiteCot { get; set; }
public string ObservacoesReq { get; set; }
public List<string> CnpjFornecedor { get; set; } = new List<string>();
public List<int> CodProduto { get; set; } = new List<int>();
}
}
I didn't understand where is the problem. what should I change to migrate the properties?
You are trying to generate a One-To-Many relationship in the wrong way. You can try the following approach:
public class DadosRequisicao
{
[Key]
[Required]
public int Id { get; set; }
public string DataLimiteCot { get; set; }
public string ObservacoesReq { get; set; }
public List<CnpjFornecedor> CnpjFornecedor { get; set; } = new();
public List<CodProduto> CodProduto { get; set; } = new();
}
public class CnpjFornecedor
{
public int Id { get; set; }
public DadosRequisicao DadosRequisicao { get; set; }
public string Data { get; set; }
}
public class CodProduto
{
public int Id { get; set; }
public DadosRequisicao DadosRequisicao { get; set; }
public int Data { get; set; }
}
Now you have a correct One-To-Many relationship with navigation property.

Cannot find the object because it does not exist or you do not have permissions when updating database

Migration is successful, yet when trying to update the database, I get that error.
I had a similar issue before, because I did not create a proper DbSet<> for the table. This time, it's not the case.
My DBContext:
using System;
using System.Collections.Generic;
using System.Text;
using ArtGalleries.Domain;
using Microsoft.EntityFrameworkCore;
namespace ArtGalleries.Data
{
public class ArtGalleriesContext:DbContext
{
public ArtGalleriesContext(DbContextOptions<ArtGalleriesContext> options):base(options)
{
}
public DbSet<ArtItem> ArtItems { get; set; }
public DbSet<Artist> Artists { get; set; }
public DbSet<Company> Companies { get; set; }
public DbSet<Floor> Floors { get; set; }
public DbSet<Location> Locations { get; set; }
public DbSet<Room> Rooms { get; set; }
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<UserLocation>()
.HasKey(u => new {u.UserId, u.LocationId});
//modelBuilder.Entity().
//modelBuilder.Entity<Company>()
// .HasOne(c => c.Company)
// .WithOne(pc => pc.Company)
// .HasForeignKey(fk => fk.ParentId);
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer(
"Server=(localdb)\\mssqllocaldb;Database=GalleriesDB;Trusted_Connection=True;");
}
}
}
}
My problem class:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text;
namespace ArtGalleries.Domain
{
public class ArtItem
{
public string ArtType { get; set; }
public Artist Artist { get; set; }
public int ArtistId { get; set; }
public int Depth { get; set; }
public string Description { get; set; }
public string Framing { get; set; }
public int Height { get; set; }
[Required]
public int Id { get; set; }
public Location Location { get; set; }
[Required]
public int LocationId { get; set; }
public string Materials { get; set; }
[Required]
public string Name { get; set; }
public User Owner { get; set; }
public int OwnerId { get; set; }
public string Picture { get; set; }
public Room Room { get; set; }
public int RoomId { get; set; }
public string Technique { get; set; }
public int Width { get; set; }
public int YearOfAcquisition { get; set; }
public int YearOfCreation { get; set; }
public Status Status { get; set; }
}
}
I am unfamiliar with permissions. I noticed a similar issue where the person was suggested to find Up() and Down() methods and work with them. I do not have such a file. It might be because their issue was generated by EF and not EF Core.
Similar problem title: “Cannot find the object ”dbo.xxxx“ because it does not exist or you do not have permissions.”
This was solved by removing the migration and adding a new migration, no edits to the code made. Weird.

Creating Code First 1:1 relationship in entity framework results in two foreign key fields

I'm trying to create a 1:1 relationship between two Entity Framework code-first models between Customer and MembershipType. Their models are:
Customer.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace Vidly.Models
{
public class Customer
{
public int Id { get; set; }
[Required]
[StringLength(255)]
public string Name { get; set; }
public bool IsSubscribedToNewsletter { get; set; }
public MembershipType MembershipType { get; set; }
[Display(Name = "Membership Type")]
public byte MembershipTypeId { get; set; }
[Display(Name = "Date of Birth")]
public DateTime? Birthdate { get; set; }
}
}
MembershipType.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Vidly.Models
{
public class MembershipType
{
public int Id { get; set; }
public string Name { get; set; }
public short SignupFee { get; set; }
public byte DurationInMonths { get; set; }
public byte DiscountRate { get; set; }
}
}
And when the migration is ran it results in the following Customer table:
Why does this happen? It's causing issues when trying to use an Html helper to create a drop down box, as when it saves it wants to put the data into the MembershipTypeId column but it appears entity is actually using the MembershipType_Id column.
you can try with the following code:
namespace Vidly.Models
{
public class Customer
{
public int Id { get; set; }
[Required]
[StringLength(255)]
public string Name { get; set; }
public bool IsSubscribedToNewsletter { get; set; }
[Display(Name = "Membership Type")]
public byte MembershipTypeId { get; set; }
[Display(Name = "Date of Birth")]
public DateTime? Birthdate { get; set; }
public virtual MembershipType MemshipType { get; set; }
}
public class MembershipType
{
public int Id { get; set; }
public string Name { get; set; }
public short SignupFee { get; set; }
public byte DurationInMonths { get; set; }
public byte DiscountRate { get; set; }
public virtual Customer customer{ get; set; }
}
}
For More info and other ways of doing the same, kindly refer this useful link:http://www.entityframeworktutorial.net/code-first/configure-one-to-one-relationship-in-code-first.aspx
Hope it will be helpful
Thanks
Karthik

Linq Include not working when item has multiple navigation properties of the same class

I am working on a project for school, and got a bit stuck on this.
A booking has 3 navigation properties, 1 customer and 2 airports.
To get the CustomerCode in one of the views for a booking, I can use (db.Bookings.Include(b => b.Customer)).
When I try to do the same for Origin and/or Destination (db.Bookings.Include(b => b.Origin)), nothing happens.
I can work around it by finding and setting both origin and destination by using a second query. (booking.Origin = db.Airports.Find(id))
But I would like to know why the Include isn't working, and if there is a more elegant way of loading the airports on a booking.
Booking class
public int BookingID { get; set; }
public int CustomerID { get; set; }
public int OriginID { get; set; }
public int DestinationID { get; set; }
public string Awb { get; set; }
public string ClientRef { get; set; }
public string Info { get; set; }
// Navigation
public virtual Airport Origin { get; set; }
public virtual Airport Destination { get; set; }
public virtual Customer Customer { get; set; }
Customer class
public int CustomerID { get; set; }
public string CustomerCode { get; set; }
public string CompanyName { get; set; }
public string VatNumber { get; set; }
Airport class
public int AirportID { get; set; }
public string AirportCode { get; set; }
Controller
public ActionResult Index()
{
var bookings = db.Bookings.Include(b => b.Origin).Include(b => b.Destination).Include(b => b.Customer);
return View(bookings.ToList());
}
Context
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;
public class AppContext : DbContext
{
// You can add custom code to this file. Changes will not be overwritten.
//
// If you want Entity Framework to drop and regenerate your database
// automatically whenever you change your model schema, please use data migrations.
// For more information refer to the documentation:
// http://msdn.microsoft.com/en-us/data/jj591621.aspx
public AppContext() : base("name=AppContext")
{
}
public System.Data.Entity.DbSet<Tester.Models.Country> Countries { get; set; }
public System.Data.Entity.DbSet<Tester.Models.Airport> Airports { get; set; }
public System.Data.Entity.DbSet<Tester.Models.Customer> Customers { get; set; }
public System.Data.Entity.DbSet<Tester.Models.Booking> Bookings { get; set; }
}
As suggested by Alexander Derck, use [ForeignKey] attribute.
Booking class
public int BookingID { get; set; }
public int CustomerID { get; set; }
[ForeignKey("Origin")]
public int OriginID { get; set; }
[ForeignKey("Destination")]
public int DestinationID { get; set; }
public string Awb { get; set; }
public string ClientRef { get; set; }
public string Info { get; set; }
// Navigation
public virtual Airport Origin { get; set; }
public virtual Airport Destination { get; set; }
public virtual Customer Customer { get; set; }
Origin is a Property. Is not possible use for include. Maybe you not like try like this:
Booking.Include(a=> a.Airport)

Foreign key attribute not available

When attempting to create an Entity Framework database model using attributes as lined out in MS Data Developer Center, I'm unable to add the ForeignKey attribute. Do I need to add another using statement to my code?
Here's a copy of the code:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace Tester.Models
{
public class MyClass
{
[Key]
public int ID { get; set; }
public string name { get; set; }
public virtual List<Note> Notes { get; set; }
public virtual List<Segment> Segments { get; set; }
}
public class Segment
{
public int ID { get; set; }
public string name { get; set; }
public virtual List<Note> segNotes { get; set; }
}
public class Note
{
public int ID { get; set; }
public DateTime notetimestamp { get; set; }
public string notestring { get; set; }
}
}
using System.ComponentModel.DataAnnotations.Schema;
Supported in .NET framework 4.5 and higher

Categories

Resources