Entity Framework firebird code first generators - entity-framework

I am learning EF6 and I want to try it with Firebird. The problem is that my generators are not created, only the tables.
public class Product
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ProductId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public int MajorVersion { get; set; }
public string PublicKey { get; set; }
public string privateKey { get; set; }
public virtual ICollection<ProductVersion> ProductVersions { get; set; }
}
When executing this code:
using (LicenseContext licenseContext = new LicenseContext())
{
Product p = new Product { Name = "Test" };
licenseContext.Products.Add(p);
licenseContext.SaveChanges();
}
I get the following error:
An exception occurred while initializing the database. See the InnerException for details.
The inner exception reads: An error was reported while committing a database transaction but it could not be determined whether the transaction succeeded or failed on the database server
The database still is being created, but with no generators or triggers for Products table. The PrimaryKey is set.
What can I try to resolve this?

If ProductId is a primary key you should to you product instance p.ProductId = 123;
Or create a trigger and generator
SET TERM;
CREATE OR ALTER TRIGGER "Product_BI" FOR "Product"
ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
new.id = gen_id("sq_Product",1);
END
SET TERM;
COMMIT;

Related

Why it is trying to insert NULL in primary key property id.. MVC5 EF6

I am using Entity Framework 6 Code First MVC5.Here is my class:
Offer.cs
public class Offer
{
public int Id { get; set; }
[Required]
public string ListOffer { get; set; }
}
Here is my controller
[HttpPost]
public ActionResult Create(OfferFormViewModel viewModel)
{
var offer = new Offer
{
ListOffer = viewModel.ListOffer,
};
_context.Offers.Add(offer);
_context.SaveChanges();
return RedirectToAction("MyOffers", "Offers");
}
OfferFormViewModel.cs
public class OfferFormViewModel {
public int Id { get; set; }
[Required]
public string ListOffer { get; set; }
}
When I try to insert a record in offers table, it works fine on my machine and inserts record in the database and it automatically assigns value to id column. But when I deploy the application it throws the exception
System.Data.SqlClient.SqlException: Cannot insert the value NULL into column 'Id', table 'DefaultConnection.dbo.Offers'; column does
not allow nulls. INSERT fails. The statement has been terminated.
My question is why is it trying to insert NULL in Id column when I deploy the application and not when I run the code without deployment?
When I deployed the application I copied the database to the server. On the server the Id column was not set to primary key and it was not an identity column either. I think something went wrong while copying the database to the server. That's why it was throwing the exception.
Use this Model and also update database with migration u can do this by following steps:
Open Tools > NuGet Package Manager > Package Manager Console.
enterenable-migrations in the Package Manager Console
enteradd-migration {name}(make sure your application can built without any error).
enterupdate-database.
public class Offer
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
public string ListOffer { get; set; }
}
You should use auto-increment, using Data Annotation:
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
or FluentAPI
modelBuilder.Entity<Offers>()
.Property(c => c.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

Entity Framework Invalid column name Height_HeightID

I am trying to get records from the Height Table based on foreign key relationships with parent table. But I am getting Invalid Column Name.... Error. Here is my model setup:-
[Table("Candidate")]
public partial class Candidate
{
public Candidate()
{
Heights = new HashSet<Height>();
Weights = new HashSet<Weight>();
}
[Key]
public int CandidateID { get; set; }
[StringLength(64)]
public string FirstName { get; set; }
[StringLength(64)]
public string LastName{ get; set; }
}
Then I have a Height and Weight Table. Model of Height table is:-
[Table("Height")]
public partial class Height
{
[Key]
public int HeightID { get; set; }
public int? CandidateID { get; set; }
public double? HeightVal { get; set; }
ForeignKey("CandidateID")]
public virtual Candidate Candidate { get; set; }
}
And here is LinQ query:-
return (from c in _db.Candidates
join h in _db.Heights
on c.CandidateID equals h.CandidateID
where c.CandidateID == candidateId
select t);
When i try to get records using these models, I am getting this error:-
System.Data.SqlClient.SqlException: Invalid column name
'Height_HeightID
As suggested by similar stackoverflow, I have added ForeignKey[] DataAnnotation but I am still getting same error.
Also in my Sql Server Database, Height Table has foreign key constraint on CandidateID.

Cascade delete on one to one does not work

I am using EF and Code First.
I have a Transaction class like this:
[Table("Transacties")]
public class Transactie
{
[Key]
[Column(Order = 1)]
[StringLength(128)]
public string KIMTransactieCode { get; set; }
[Column(Order = 2)]
[StringLength(128)]
public string BovenliggendeKIMTransactieCode { get; set; }
[ForeignKey("BovenliggendeKIMTransactieCode")]
public Transactie BovenLiggendeTransactie { get; set; }
public DateTime? DatumLaatstBekeken { get; set; }
public bool? IsZichtbaar { get; set; }
public DateTime? IsZichtbaarGewijzigdOp { get; set; }
public OpnameInfo OpnameInfo { get; set; }
}
The relation is as follows:
A transaction can have a subtransaction, when there is subtransaction a reference is required to the parent transaction ('BovenliggendeKIMTransactieCode'). This is complete defined in one class/table.
It uses mainly data annotations.
I want to have a cascade delete on this class: when the (parent) transaction is deleted, all the related subtransactions must be deleted also.
I tried to invoke cascade delete as follows:
var transactions = mailboxDataContext.Transacties
.Where(tr => tr.BovenliggendeKIMTransactieCode == null &&
tr.IsZichtbaar.HasValue &&
!tr.IsZichtbaar.Value &&
tr.IsZichtbaarGewijzigdOp.HasValue &&
tr.IsZichtbaarGewijzigdOp.Value < selectionDateTime)
.ToList(); // Materialize
if (transactions.Count > 0)
{
foreach (var transaction in transactions)
{
mailboxDataContext.SetDeleted(transaction);
}
mailboxDataContext.SaveChanges();
}
but then I get:
"The DELETE statement conflicted with the SAME TABLE REFERENCE
constraint
\"FK_dbo.Transacties_dbo.Transacties_BovenliggendeKIMTransactieCode\".
The conflict occurred in database \"PROGISKIM_Mailbox\", table
\"dbo.Transacties\", column 'BovenliggendeKIMTransactieCode'.\r\nThe
statement has been terminated."
How can this be fixed ?
Update:
When I try to delete the main row in SSMS I get this exception also...

One to Many Relationship in Entity Framework with Composite Key

I have the following class that I would like to use as property of a Login object. I'd prefer that this class not have any navigation properties (as it will just be used for quick checks) if that is at all possible, but I'm willing to allow the one shown below.
public class LoginFeature
{
[Key, Column(Order = 0)]
public int RoleId { get; set; } //Role is another table in the db, but not looking for a nav. property or constraint here.
[Key, Column(Order = 1)]
public virtual Login Login { get; set; }
public bool Deny { get; set; }
}
The class containing a collection of these is (stripped down for space)
public class Login
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; } //Database ID
public virtual List<LoginFeature> LoginFeatures { get; set; }
}
My DbContext is defined as
public class MyContext : DbContext
{
public DbSet<Login> Logins { get; set; }
public DbSet<LoginFeature> LoginFeatures { get; set; }
}
But the following test generates an error saying that
System.Data.Entity.Infrastructure.DbUpdateException : An error occurred while saving entities that do not expose foreign key properties for their relationships. The EntityEntries property will return null because a single entity cannot be identified as the source of the exception. Handling of exceptions while saving can be made easier by exposing foreign key properties in your entity types. See the InnerException for details.
----> System.Data.UpdateException : An error occurred while updating the entries. See the inner exception for details.
----> System.Data.SqlClient.SqlException : Cannot insert the value NULL into column 'RoleId', table 'TEST.dbo.LoginFeatures'; column does not allow nulls. INSERT fails.
The statement has been terminated.
[Test]
public void LoginCanHaveFeatures()
{
using (var ctx = new MyContext())
{
var login = ctx.Logins.FirstOrDefault(x => x.Id == 30);
Assert.IsNotNull(login);
for (int i = 10; i < 15; i++)
{
var feature = new LoginFeature();
feature.Login = login;
feature.RoleId = i;
feature.Deny = true;
login.LoginFeatures.Add(feature);
}
ctx.SaveChanges();
}
}
The SQL being generated as show in EFProf is
insert [dbo].[LoginFeatures]
([Deny],
[Login_Id])
values (1 /* #0 */,
30 /* #1 */)
Which seems to imply that the data annotation attributes on LoginFeature are incorrect. Is what I am trying to do possible?
Thanks,
Joe
You cannot define a navigation property as a key. Only primitive properties are supported as keys. So, you should define the class like so:
public class LoginFeature
{
[Key, Column(Order = 0)]
public int RoleId { get; set; }
[Key, Column(Order = 1)]
public int LoginId { get; set; }
public virtual Login Login { get; set; }
public bool Deny { get; set; }
}
Mapping conventions will detect LoginId as foreign key for Login. The error probably occurs because EF did ignore your second key attribute (as it was on a navigation property), uses only the first key RoleId and by default (for single keys) assumes that the key is autogenerated in the database (which it apparently isn't) and doesn't send its value to the database.

How can I update a Code First application to accommodate manual schema changes?

I have an app that was created using EF. The problem is that I noticed some extraneous foreign keys columns created in one of the tables. Dropping these columns causes an [SqlException (0x80131904): Invalid column name 'Material_Id' error.
Here is a simplified version of the class structure...
public class Hazard
{
public int Id { get; set; }
public string Name { get; set; }
}
public abstract class HazardAnalysis
{
public int Id { get; set; }
public int HazardId { get; set; }
public virtual Hazard Hazard { get; set; }
}
public class ProductHazard : HazardAnalysis
{
public int ProductId { get; set; }
public virtual Product Product { get; set; }
}
The table that was generated looked like this...
dbo.Hazards
Id int
Name string
Product_Id int
Since the relationship between ProductHazards and Hazards is 1:many, the Product_Id field should not be there. Dropping this column generates the Invalid column name 'Product_Id' error.
I've scoured the model for hours and can't find any valid reason for this column to exist.
Is there any way to update the model after manually dropping a column? I obviously don't want to drop and recreate the database.
I've also noticed that the productId of the current product is inserted in the dbo.Hazards Product_Id table whenever a new ProductHazard is created. Since there is a many-to-one relationship between ProductHazards and Hazards, when a new ProductHazard is created, the Product_Id field is updated with the ProductId of the new ProductHazard, which seems bizarre.
Any advice would be greatly appreciated.
Here is the DbSet code:
public DbSet<Hazard> Hazards { get; set; }
public DbSet<HazardAnalysis> HazardAnalyses { get; set; }
and also...
modelBuilder.Entity<HazardAnalysis>()
.HasRequired(e => e.Hazard)
.WithMany()
.HasForeignKey(e => e.HazardId)
.WillCascadeOnDelete(false);
You need to define the many part of the relationship. In this case, you need to add a collection property to your Hazard object, like below:
public class Hazard
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<HazardAnalysis> HazardAnalyses { get; set; }
}