Two FK's pointing to the same column in another table - sql

I have
public class Customer
{
public int Id { get; set; }
public int RepresentativeId { get; set; }
public int ChargeRepresentativeId { get; set; }
}
public class Representative
{
public int Id { get; set; }
public string Number { get; set; }
public string Name { get; set; }
}
Every Customer has its own Representative represented with RepresentativeId column, but also in certain scenarios I want to create new Customer with both RepresentativeId and its ChargeRepresentativeId.
I already have a FK constraint applied on RepresentativeId column
ALTER TABLE [Representatives] ADD CONSTRAINT [FK_Customers_Representatives]
FOREIGN KEY([RepresentativeId]) REFERENCES [Representative] ([Id])
How can I force ChargeRepresentativeId to be valid data which exists in the Representatives table (the case I already have for the RepresentativeId)?

Related

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

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

Foreign key may cause cycles or multiple cascade paths entity framework core

I am using Entity Framework core and I added a model called CourseOffering to my project. This model is related to other classes like Section. I successfully created a migration for it. The problem is when I try to apply the migration to the database. I get the following error:
Introducing FOREIGN KEY constraint 'FK_CourseOfferings_Sections_SectionId' on table 'CourseOfferings' 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.
I was trying to turn off cascade delete with FluentAPI, but I'm not entirely sure if that is the right solution to my problem. I mean is this totally safe to turn off cascade delete?
My CourseOffering model:
public class CourseOffering
{
public int Id { get; set; }
public Section Section { get; set; }
public Instructor Instructor { get; set; }
public Course Course { get; set; }
public AcademicSemester AcademicSemester { get; set; }
public int SectionId { get; set; }
public int InstructorId { get; set; }
public int? CourseId { get; set; }
public int AcademicSemesterId { get; set; }
}
My Section Model:
public class Section
{
public int Id { get; set; }
[Required]
[StringLength(10)]
public string Name { get; set; }
public int EntranceYear { get; set; }
public int StudentCount { get; set; }
public Department Department { get; set; }
public ProgramType Program { get; set; }
public AdmissionLevel AdmissionLevel { get; set; }
public ICollection<RoomSectionAssignment> RoomAssignments { get; set; }
public int DepartmentId { get; set; }
public int ProgramTypeId { get; set; }
public int AdmissionLevelId { get; set; }
public Section()
{
RoomAssignments = new Collection<RoomSectionAssignment>();
}
}
The migration created all the necessary foreign keys but there is cascade path that would cause cycles. I am not able to figure out what caused the cycle. Should I just turn off cascade delete with FluentAPI?
I was trying to turn off cascade delete with FluentAPI, but I'm not entirely sure if that is the right solution to my problem. I mean is this totally safe to turn off cascade delete?
Yes! This is the appropriate solution in this case! Moreover yes! This is completely safe to turn off cascade delete using FluentAPI because FluentAPIwill generate constraint on database too.

ASP EF7 Set column value in migration

I want to move from autoincrement ids to composite primary keys. So, these two entities
public class SeasonTeam
{
public int SeasonTeamId { get; set; }
public int SeasonId { get; set; }
public int TeamId { get; set; }
}
public class GroupEntry
{
public int GroupEntryId { get; set; }
public int SeasonTeamId { get; set; }
public SeasonTeam SeasonTeam { get; set; }
}
will now look like this
public class SeasonTeam
{
public int SeasonId { get; set; }
public int TeamId { get; set; }
}
public class GroupEntry
{
public int GroupEntryId { get; set; }
public int SeasonId { get; set; }
public int TeamId { get; set; }
public SeasonTeam SeasonTeam { get; set; }
}
Visual Studio generated migration code, but it corrupts data.
migrationBuilder.AddColumn<int>(
name: "SeasonId",
table: "GroupEntry",
nullable: false,
defaultValue: 0);
migrationBuilder.AddColumn<int>(
name: "TeamId",
table: "GroupEntry",
nullable: false,
defaultValue: 0);
migrationBuilder.DropForeignKey(name: "FK_GroupEntry_SeasonTeam_SeasonTeamId", table: "GroupEntry");
migrationBuilder.DropPrimaryKey(name: "PK_SeasonTeam", table: "SeasonTeam");
migrationBuilder.DropColumn(name: "SeasonTeamId", table: "SeasonTeam");
Default value 0 obviously won't work, I need ids from referenced SeasonTeam table, but I didn't find any examples. How can I set proper id values for a new composite key before I delete old primary key column?
You can't do this programmatically with EF's APIs, however, if you can write the SQL to move the values from one table to another, you can add a custom migration step after the Add column operations and before the drop column operations.
migrationBuilder.Sql(#"INSERT INTO ...(your SQL here)");
From the limited info in your question, I can't tell you what that SQL should be.

How to Insert data in table when Foreign Key is not a primary key

I created a Model with Entity Framework Code First and have two classes
Product.cs
public class Product
{
public Product()
{
Certificates = new HashSet<Certificate>();
}
public int ProductId { get; set; }
public int ProductCode { get; set; }
public decimal Price { get; set; }
public string Type { get; set; }
public string SubType { get; set; }
public int RelatedProductId { get; set; }
public string Description { get; set; }
public string DescriptionSpanish { get; set; }
public string ShortDescription { get; set; }
public string CertificateDescription { get; set; }
public string QBItemCode { get; set; }
public string QBDescCode { get; set; }
public virtual ICollection<Certificate> Certificates { get; set; }
}
Certificate.cs
public class Certificate
{
public int CertificateId { get; set; }
public string Type { get; set; }
public string Course { get; set; }
public DateTime DateGranted { get; set; }
public string NameOnCertificate { get; set; }
public int FinalExamQuestionsCorrect { get; set; }
public int FinalExamQuestionsTotal { get; set; }
public string ClientIPAddress { get; set; }
public int ProductCode { get; set; }
public virtual Product Product { get; set; }
public string UserId { get; set; }
public virtual ApplicationUser ApplicationUser { get; set; }
}
ProductConfiguration.cs
public class ProductConfiguration : EntityTypeConfiguration<Product>
{
public ProductConfiguration()
{
HasKey(p => p.ProductId);
Property(p => p.ProductId)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(p => p.ProductCode)
.HasColumnAnnotation("Index",
new IndexAnnotation(new IndexAttribute("AK_Product_ProductCode") { IsUnique = true }));
}
}
CertificateConfiguration.cs
public class CertificateConfiguration : EntityTypeConfiguration<Certificate>
{
public CertificateConfiguration()
{
HasKey(c => c.CertificateId);
Property(c => c.CertificateId)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(p => p.ProductCode).HasColumnName("ProductId");
HasRequired(c => c.ApplicationUser)
.WithMany(u => u.Certificates)
.HasForeignKey(c => c.UserId);
HasRequired(c => c.Product)
.WithMany(p => p.Certificates)
.HasForeignKey(c => c.ProductCode);
}
}
Notice, I created a Foreign Key ProductCode (rename it to ProductId) in Certificate Table.
I also seeded Product table with some data in which the ProductId generated by database and ProductCode that I manually defined. The problem is when I am trying to insert a record in Certificate table by running a sql query in which I defined a foreign key that's actually a ProductCode (not ProductId), it throws an error
SQL QUERY:
Insert into [dbo].[Certificates]
values (
'TestType','TestCourse',GETUTCDATE(),'TestName',1,5,
'127.0.0.1',201,'userId'
)
201 is the ProductCode in query that exist in Product table
Error
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_dbo.Certificates_dbo.Products_ProductId". The conflict occurred in database "myDatabse", table "dbo.Products", column 'ProductId'.
I am not sure why it's looking for Primary Key ProductId. It should look for the ProductCode in Product table weather it exist or not.
I believe you're running into a limitation of EF whereby your FK on the dependent end of the relationship has to refer back to the PK on the principal end. When you configure the relationship between Product and Certificates here:
HasRequired(c => c.Product)
.WithMany(p => p.Certificates)
.HasForeignKey(c => c.ProductCode);
this establishes the foreign key relationship between the Product primary key - Product.ProductId - and the foreign key you defined - Certificate.ProductCode (named Certificate.ProductId in your table).
While the database will support FK referring back to a unique key in your table, EF does not support it (at this time).
Here are a few other SO questions that cover this issue:
How to get EF6 to honor Unique Constraint (on FK) in Association/Relationship multiplicity?
Database first Entity Framework mapping unique foreign keys as one to many
And here's the official feature request to add this feature to EF:
Unique Constraint (i.e. Candidate Key) Support
According to the comments, it looks like they are working adding this in EF7.

saving reference using ServiceStack ORMLite

I am using ORMLite as my ORM and I am using it with following structure which contains the foreign key relation ship:
public class Order
{
[AutoIncrement]
public int Id { get; set; }
[Reference]
public Item Item { get; set; }
public string ProUserId { get; set; }
public string Details { get; set; }
}
public class Item
{
[AutoIncrement]
public int Id { get; set; }
public string Description { get; set; }
}
As we can see that Order contains the reference to the Item. In DB Order table has a foreign key called ItemId in the table and I have annotated that key in the design view with [Reference] attribute.
I am trying to save the Order with following code:
var order = new Order
{
Item = new Item
{
Id = 3,
Description = "Something"
},
ProUserId = "kunal#kunal.com",
Details = "fdfsdfsd"
};
Db.Save(order,references:true);
I was hoping that ORMLite would pick up the relationship and with ItemID in the Order table but it did not and it did throw following error instead:
Cannot insert the value NULL into column 'ItemId', table 'WebApp.dbo.Order'; column does not allow nulls. INSERT fails.
I tried changing my schema and addred OrderId column in my Item table with reference there and that works fine. But that is not the correct design. Should I make any changes in my code/schema to support this feature?
You still need to provide the foreign key that OrmLite can use to store the relationship, e.g. either on the Child/ForeignKey table:
public class Order
{
[AutoIncrement]
public int Id { get; set; }
[Reference]
public Item Item { get; set; }
public string ProUserId { get; set; }
public string Details { get; set; }
}
public class Item
{
[AutoIncrement]
public int Id { get; set; }
public int OrderId { get; set; } //Parent Table PK
public string Description { get; set; }
}
Or for 1:1 relationships, can be on the Parent table, e.g:
public class Order
{
[AutoIncrement]
public int Id { get; set; }
[Reference]
public Item Item { get; set; }
public int ItemId { get; set; } //Child Table PK
public string ProUserId { get; set; }
public string Details { get; set; }
}
public class Item
{
[AutoIncrement]
public int Id { get; set; }
public string Description { get; set; }
}