EntityFramework Trying to create multiple links to the same table, FK Constraint error - sql

I have a table called DeliveryRequest and another table called Operator, table DeliveryRequest is as follows:
public class DeliveryRequest
{
public int ID { get; set; }
public DateTime Date { get; set; }
public string UserID { get; set; }
public string Waybill { get; set; }
public string Reference { get; set; }
public int SupplierID { get; set; }
public Supplier Supplier { get; set; }
//[ForeignKey("Operator")]
public int SenderID { get; set; }
public Operator Sender { get; set; }
//[ForeignKey("Operator")]
public int ReceiverID { get; set; }
public Operator Receiver { get; set; }
public string Origin { get; set; }
public string Destination { get; set; }
public int ServiceID { get; set; }
public Service Service { get; set; }
}
And table Operator is as follows:
public class Operator
{
public int ID { get; set; }
public string Company { get; set; }
public int ContactID { get; set; }
public Contact Contact { get; set; }
public int AddressID { get; set; }
public Address Address { get; set; }
}
So the problem is, when I am trying to update my database I get a FK Constraint error as follows:
Introducing FOREIGN KEY constraint
'FK_dbo.DeliveryRequests_dbo.Operators_SenderID' on table
'DeliveryRequests' may cause cycles or multiple cascade paths. Specify
ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN
KEY constraints.
Could not create constraint or index. See previous errors.
And the previous error is the same. As follows:
System.Data.SqlClient.SqlException (0x80131904): Introducing FOREIGN
KEY constraint 'FK_dbo.DeliveryRequests_dbo.Operators_SenderID' on
table 'DeliveryRequests' may cause cycles or multiple cascade paths.
Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other
FOREIGN KEY constraints.
Focus on the Sender and Receiver part, I am no expert but the error must be there lol
//[ForeignKey("Operator")]
public int SenderID { get; set; }
public Operator Sender { get; set; }
//[ForeignKey("Operator")]
public int ReceiverID { get; set; }
public Operator Receiver { get; set; }

It looks like you are using Code First approach. So try to turn off CascadeDelete for DeliveryRequests:
modelBuilder.Entity<DeliveryRequests>()
.HasRequired(c => c.Operator )
.WithMany()
.WillCascadeOnDelete(false);
For example:
public class YourDBContext: DbContext
{
public YourDBContext(): base()
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<DeliveryRequests>()
.HasRequired(c => c.Operator )
.WithMany()
.WillCascadeOnDelete(false);
}
}

Related

Using database-first approach with string primary key and a one-to-many relationship not working in ASP.NET Core Web API

I have two model classes:
public partial class customer
{
public string customer_id { get; set; } // Primary Key
public string customer_name { get; set; }
public string course_mobile { get; set; }
public List<customer_address> customer_addresses { get; set; }
}
public partial class customer_address
{
public string address_id { get; set; } // Primary Key
public string adreess { get; set; }
public customer customer { get; set; }
public string customer_id { get; set; } // Foreign Key
}
I get an error:
The entity type 'customer' requires a primary key to be defined.
So how it solve?
Datbase table structure
You need to add [Key] attrubute.
public partial class customer
{
[Key]
public string customer_id { get; set; } // Primary Key
public string customer_name { get; set; }
public string course_mobile { get; set; }
public List<customer_address> customer_addresses { get; set; }
}
public partial class customer_address
{
[Key]
public string address_id { get; set; } // Primary Key
public string adreess { get; set; }
public customer customer { get; set; }
public string customer_id { get; set; } // Foriegn Key
}

Object reference not set to an instance of an object in .net core

I have two model class as;
public class MessageDetailModel
{
[Key]
public int messageDetailsId { get; set; }
public MessageModel messageModel { get; set; }
public string detail { get; set; }
public int senderId { get; set; }
public int customerId { get; set; }
public string phone { get; set; }
public DateTime date { get; set; }
}
and
public class MessageModel
{
[Key]
public int messageId { get; set; }
public int senderId { get; set; }
public int customId { get; set; }
public bool ReadInfo { get; set; }
public virtual List<MessageDetailModel> MessageDetails { get; set; }
}
and it is my context class ;
public virtual DbSet<MessageDetailModel> messageDetails { get; set; }
public virtual DbSet<MessageModel> messages { get; set; }
public virtual DbSet<PersonModel> persons { get; set; }
public virtual DbSet<DirectoryModel> directory { get; set; }
I am trying to get messageId over MessageDetailModel but messageId returns as 0 and I have that error "Object reference not set to an instance of an object"
Console.WriteLine(k.messageModel.messageId); //( k is my var which gets from messagedetail model)
How can ı reach messageId over MessadeDetailModel
There is no current link between your two models that would represent a Foreign Key.
You'd need to do something like this for your model if you want a Foreign Key to link to the related object:
public class MessageDetailModel
{
[Key]
public int messageDetailsId { get; set; }
[ForeignKey("messageId")] // Added Data Annotation for the Foreign Key relationship
public MessageModel messageModel { get; set; }
public string detail { get; set; }
public int senderId { get; set; }
public int customerId { get; set; }
public string phone { get; set; }
public DateTime date { get; set; }
public int messageId { get; set; } // This would be your Foreign Key
}
I've added the messageId column to your MessageDetailModel to match the Primary Key column of your MessageModel as that's necessary for the link to form.
You would use the [ForeignKey("messageId")] Data Annotation above the variable for the MessageModel to determine what value it needs to use when finding the object you want.

EF Core Join using Include but ForeignKey is not Primary Key on the other table

I am trying to relate my Tables with ForeignKey and PrimaryKey on the other end. But now i will be using a ForeignKey which is not the primary for the said table. I was using [InverseProperty] but i think there's a bug with it since i've been looking around for hours already and all of them says the same thing about it.
Documents Table:
public class Document
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int DocumentId { get; set; }
public int ProjectId { get; set; }
public int DepartmentId { get; set; }
public int AuthorId { get; set; }
[NotMapped]
public virtual User Author { get; set; }
}
Users
public class User
{
[Key]
public int UserId { get; set; }
public int AuthUserId { get; set; }
public string DisplayName { get; set; }
[NotMapped]
[ForeignKey("AuthorId")]
public virtual Document Document { get; set; }
}
Context:
modelBuilder.Entity<User>(entity =>
{
entity.HasOne(u => u.Document)
.WithMany("AuthorId");
});
I am trying to use the solution they here, but no luck.
Any help would really be appreciated. Thanks!
But now i will be using a ForeignKey which is not the primary for the said table.
To do this you can use EF Core Alternate Keys feature. But first correct your model class set up as follows: (As you said a User will have multiple Document)
public class Document
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int DocumentId { get; set; }
public int ProjectId { get; set; }
public int DepartmentId { get; set; }
public int AuthorId { get; set; }
public User Author { get; set; }
}
public class User
{
[Key]
public int UserId { get; set; }
public int AuthUserId { get; set; }
public string DisplayName { get; set; }
public ICollection<Document> Documents { get; set; }
}
Then in the Fluent API configuration as follows:
modelBuilder.Entity<Document>()
.HasOne(p => p.Author)
.WithMany(b => b.Documents)
.HasForeignKey(p => p.AuthorId)
.HasPrincipalKey(b => b.AuthUserId); // <-- here you are specifying `AuthUserId` as `PrincipalKey` in the relation which is not primary key

Is it possible to create a Domain Class which has Multiple FK Columns to same PK?

I'm a newbie to designing database.
I have problem how to define a domain class which has multiple foreign keys linked with a same primary key.
Here is my model:
namespace OceanFmsSystem.Domain
{
public class ExportTemplate
{
public int Id { get; set; }
public List<ExportBooking> ExportBookings { get; set; }
public string TemplateName { get; set; }
public int CustomerId { get; set; }
public string Incoterms { get; set; }
public string IncotermsDetail { get; set; }
public string PaymentTerm{ get; set; }
public int CountryOriginId { get; set; }
public int CountryDestinationId { get; set; }
}
}
What I want to do is that CountryOriginId & CountryDestinationId should refer to the below class as foreign keys:
namespace OceanFmsSystem.Domain
{
public class Country
{
public int Id { get; set; }
public string CountryCode { get; set; }
public string CountryName { get; set; }
}
}
As far as I know, in EF Core there is an convention which I should name a foreign key as below for migration from code to database.
public type ClassNameOfPrimaryKeyId { get; set;}
Is there any possible way to make this happens?
Yes, possible. Your class should look like this:
public class ExportTemplate
{
//...
public int CountryOriginId { get; set; }
public Country CountryOrigin { get; set; }
public int CountryDestinationId { get; set; }
public Country CountryDestination { get; set; }
}
EF is smart enough to figure the Ids by convention. If you do not wish to follow the convention you can use [ForeignKey] attribute on the properties to configure the FK:
[ForeignKey("Origin")]
public int MyOriginId { get; set; }
public Country Origin { get; set; }

Entity Relationship - CodeFirst - Multiple Relationships

I'm trying to create the following object for my DB (CodeFirst),
And i have the following problem:
when i try to add new one or many object to a new srevice provider slots (as follows:)
ServiceProviderSlots slot = new ServiceProviderSlots();
slot.ServiceProviderID = 1;
slot.SlotServices.Add(new ServiceProviderServices() { ServiceProviderServiceID = 1 });
ctx.ServiceProviderSlots.Add(slot);
I get an error, because i'm not creating a new object, and i'm missing foreign keys, but i wish to use data which already exists on that table.
ERROR:
{"The INSERT statement conflicted with the FOREIGN KEY constraint \"FK_dbo.ServiceProviderServices_dbo.ServiceProviders_ServiceProviderID\". The conflict occurred in database \"qunadodb\", table \"dbo.ServiceProviders\", column 'ServiceProviderID'.\r\nThe statement has been terminated."}
Maybe it's related to this?
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
}
Which i used becuase i couldn't create the db otherwise, i had another error.
See below structure:
public class BusinessCategories
{
[Key]
public int CategoryID { get; set; }
public String Title { get; set; }
}
public class BusinessTypes
{
[Key]
public int TypeID { get; set; }
public String Title { get; set; }
public int CategoryID { get; set; }
public virtual BusinessCategories Categories { get; set; }
}
public class ServiceProviders
{
[Key]
public int ServiceProviderID { get; set; }
public String Name { get; set; }
public Int32 TypeID { get; set; }
public virtual BusinessTypes Type { get; set; }
}
public class ServiceProviderServices
{
[Key]
public Int32 ServiceProviderServiceID { get; set; }
public String Price { get; set; }
public Int32 ServiceProviderID { get; set; }
public virtual ServiceProviders ServiceProvider { get; set; }
public Int32 SubServiceID { get; set; }
public virtual SubServices SubService { get; set; }
}
public class ServiceProviderSlots
{
public ServiceProviderSlots()
{
SlotServices = new List<ServiceProviderServices>();
}
[Key]
public Int32 SlotID { get; set; }
public String Name { get; set; }
public Int32 ServiceProviderID { get; set; }
[ForeignKey("ServiceProviderID")]
public virtual ServiceProviders ServiceProvider { get; set; }
public virtual ICollection<ServiceProviderServices> SlotServices { get; set; }
}
this message means that you probably yet have a ServiceProvider with Id = 1 in the database.
in this cas you have to attach the entity to the context.