i try to create sqlite db using EF7.
the class:
public class Item
{
//primaery key, not identity
public string id { get; set; }
//not primery key, but needed autoincerment
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int numberInc { get; set; }
}
but in the table genereted numberInc its a normal column:
CREATE TABLE "VideoItem" (
"id" TEXT NOT NULL CONSTRAINT "PK_VideoItem" PRIMARY KEY,
"numberInc" INTEGER NOT NULL,
)
i also tried setting the column in OnModelCreating:
modelBuilder.Entity<VideoItem>().Property(x => x.numberInc).UseSqlServerIdentityColumn();
but any effect.
iwm use EntityFramework.Sqlite 7.0.0-rc1-final.
Related
Trying to do a basic one-to-many relationship but getting the below error. It's adding another accountstatusid column in the query but the duplicate has an additional 1 at the end.
Error:
Npgsql.PostgresException (0x80004005): 42703: column a.accountstatusid1 does not exist
Generated Query
SELECT a.accountid, a.accountstatusid, a.accountstatusid1, a.name
FROM account AS a
WHERE a.accountid = #__accountId_0
LIMIT 2
Database
CREATE TABLE accountstatus
(
accountstatusid smallint NOT NULL GENERATED ALWAYS AS IDENTITY,
name character varying(128) NOT NULL,
CONSTRAINT accountstatus_pkey PRIMARY KEY (accountstatusid)
)
CREATE TABLE account
(
accountid integer NOT NULL GENERATED ALWAYS AS IDENTITY,
accountstatusid smallint NOT NULL,
name character varying(256) NOT NULL,
CONSTRAINT account_pkey PRIMARY KEY (accountid),
CONSTRAINT fk_accountstatusidid FOREIGN KEY (accountstatusid)
)
Models
public class Account
{
public int AccountId { get; set; }
public string Name { get; set; }
public short AccountStatusId { get; set; }
public virtual AccountStatus AccountStatus { get; set; }
}
public class AccountStatus
{
public int AccountStatusId { get; set; }
public string Name { get; set; }
}
DataContext
public class DataContext : DbContext
{
public DbSet<AccountStatus> AccountStatuses { get; set; }
public DbSet<Account> Accounts { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<AccountStatus>().ToTable("accountstatus");
modelBuilder.Entity<Account>(x =>
{
x.ToTable("account");
x.HasOne(x => x.AccountStatus);
});
}
}
The reason is that AccountStatus has Key of type int and your foreign key(Account.AccountStatusId) is of type short and the EF is not recognized Account.AccountStatusId as a foreign key to AccountStatus table and creates a new field.
If this won`t help you could try to set up a foreign key inside your model configuration.
I'm trying to create a tables using Code-First in EF.
I created many versions of my code but I put here only one. It almost works, it means this code creates sql but doesn't work properly.
What I want to get:
I have 2 simple tables : Order and Payer.
Also, I want to create a third table based on foreign keys of these 2.
It wont create it that meet the following rules:
Each Order has exactly one Base Payer. (So I don't need complex key in this case. OrderId can exist only one in this table if record is type of (Base)OrderPayer
Each Order can have 0,1 or many (Extra)OrderPayer. ( So in this case i need put into table complex Key (OrderId + PayerId)
here is my last C# code
public class Order
{
[Key]
public int OrderId { get; set; }
public string OrderName { get; set; }
public virtual BaseOrderPayer BaseOrderPayer { get; set; }
public virtual ICollection<ExtraOrderPayer> ExtraOrderPayers { get; set; }
}
public class Payer
{
[Key]
public int PayerId { get; set; }
public string PayerName { get; set; }
}
public abstract class OrderPayer
{
[Column(Order = 0), Key, ForeignKey("Order")]
public int OrderId { get; set; }
public virtual Order Order { get; set; }
}
public class BaseOrderPayer : OrderPayer
{
[ForeignKey("BasePayer")]
public virtual int? BasePayerId { get; set; }
public virtual Payer BasePayer { get; set; }
}
public class ExtraOrderPayer : OrderPayer
{
[Column(Order = 1), Key, ForeignKey("ExtraPayer")]
public virtual int? ExtraPayerId { get; set; }
public virtual Payer ExtraPayer { get; set; }
}
and SQL that was generated by Update-Database -Script
CREATE TABLE [dbo].[OrderPayers] (
[OrderId] [int] NOT NULL,
[ExtraPayerId] [int],
[BasePayerId] [int],
[Discriminator] [nvarchar](128) NOT NULL,
[Order_OrderId] [int],
CONSTRAINT [PK_dbo.OrderPayers] PRIMARY KEY ([OrderId])
)
CREATE TABLE [dbo].[Payers] (
[PayerId] [int] NOT NULL IDENTITY,
[PayerName] [nvarchar](30),
CONSTRAINT [PK_dbo.Payers] PRIMARY KEY ([PayerId])
)
CREATE TABLE [dbo].[Orders] (
[OrderId] [int] NOT NULL IDENTITY,
[OrderName] [nvarchar](30),
[BaseOrderPayer_OrderId] [int],
CONSTRAINT [PK_dbo.Orders] PRIMARY KEY ([OrderId])
)
CREATE INDEX [IX_OrderId] ON [dbo].[OrderPayers]([OrderId])
CREATE INDEX [IX_ExtraPayerId] ON [dbo].[OrderPayers]([ExtraPayerId])
CREATE INDEX [IX_BasePayerId] ON [dbo].[OrderPayers]([BasePayerId])
CREATE INDEX [IX_Order_OrderId] ON [dbo].[OrderPayers]([Order_OrderId])
CREATE INDEX [IX_BaseOrderPayer_OrderId] ON [dbo].[Orders]([BaseOrderPayer_OrderId])
ALTER TABLE [dbo].[OrderPayers] ADD CONSTRAINT [FK_dbo.OrderPayers_dbo.Payers_BasePayerId] FOREIGN KEY ([BasePayerId]) REFERENCES [dbo].[Payers] ([PayerId])
ALTER TABLE [dbo].[OrderPayers] ADD CONSTRAINT [FK_dbo.OrderPayers_dbo.Payers_ExtraPayerId] FOREIGN KEY ([ExtraPayerId]) REFERENCES [dbo].[Payers] ([PayerId])
ALTER TABLE [dbo].[OrderPayers] ADD CONSTRAINT [FK_dbo.OrderPayers_dbo.Orders_Order_OrderId] FOREIGN KEY ([Order_OrderId]) REFERENCES [dbo].[Orders] ([OrderId])
ALTER TABLE [dbo].[OrderPayers] ADD CONSTRAINT [FK_dbo.OrderPayers_dbo.Orders_OrderId] FOREIGN KEY ([OrderId]) REFERENCES [dbo].[Orders] ([OrderId])
ALTER TABLE [dbo].[Orders] ADD CONSTRAINT [FK_dbo.Orders_dbo.OrderPayers_BaseOrderPayer_OrderId] FOREIGN KEY ([BaseOrderPayer_OrderId]) REFERENCES [dbo].[OrderPayers] ([OrderId])
but his SQL it doesn't even work
I can't insert Order because it need OrderPayer and vice versa :)
Is it possible to fix it according to my expectations ?
p.s.
the tables are very simplified, in fact they contain many other fields
I use in some project EF code First with TPH (in part of classes)
I have class like this:
namespace Billing.Model.Domain.Entities.BilProject
{
[Table("ProjectPriceList")]
public abstract class ProjectPriceList
{
[Key, Column("ProjectId", Order = 0)]
public int ProjectId { get; set; }
[Key, Column("PriceListId", Order = 1)]
public int PriceListId { get; set; }
[Key, Column("PriceListSourceType", Order = 2)]
public int PriceListSourceType { get; set; }
[ForeignKey("PriceListSourceType")]
public virtual BillingProjectCode PriceListSourceTypeCode { get; set; }
public int AddUsrnm { get; set; }
public DateTime AddTmstmp { get; set; }
[ForeignKey("ProjectId")]
public virtual BillingProject BillingProject { get; set; }
public virtual SnapShotPriceList SnapShotPriceList{ get; set; }
}
public class BillingProjectPriceList : ProjectPriceList
{
[ForeignKey("PriceListId")]
public virtual PriceList PriceList { get; set; }
}
public class EstimateProjectPriceList : ProjectPriceList
{
}
}
When I try to generate sql code to create a data base by
Update-Database -Script from console
I receive this SQL as result:
CREATE TABLE [dbo].[ProjectPriceList] (
[ProjectId] [int] NOT NULL,
[PriceListId] [int] NOT NULL,
[PriceListSourceType] [int] NOT NULL,
[AddUsrnm] [int] NOT NULL,
[AddTmstmp] [datetime] NOT NULL,
[Discriminator] [nvarchar](128) NOT NULL,
CONSTRAINT [PK_dbo.ProjectPriceList] PRIMARY KEY ([ProjectId], [PriceListId], [PriceListSourceType])
)
CREATE INDEX [IX_ProjectId] ON [dbo].[ProjectPriceList]([ProjectId])
CREATE INDEX [IX_PriceListId] ON [dbo].[ProjectPriceList]([PriceListId])
CREATE INDEX [IX_PriceListSourceType] ON [dbo].[ProjectPriceList]([PriceListSourceType])
ALTER TABLE [dbo].[ProjectPriceList] ADD CONSTRAINT [FK_dbo.ProjectPriceList_dbo.BillingProject_ProjectId] FOREIGN KEY ([ProjectId]) REFERENCES [dbo].[BillingProject] ([ProjectId]) ON DELETE CASCADE
ALTER TABLE [dbo].[ProjectPriceList] ADD CONSTRAINT [FK_dbo.ProjectPriceList_dbo.BillingProjectCode_PriceListSourceType] FOREIGN KEY ([PriceListSourceType]) REFERENCES [dbo].[BillingProjectCode] ([CodeId]) ON DELETE CASCADE
ALTER TABLE [dbo].[ProjectPriceList] ADD CONSTRAINT [FK_dbo.ProjectPriceList_dbo.PriceList_PriceListId] FOREIGN KEY ([PriceListId]) REFERENCES [dbo].[PriceList] ([PriceListId]) ON DELETE CASCADE
The last FK Constraint is redudant and make me trouble if i try add new EstimateProjectPriceList.
My question is
How to stop create this FK by some code Data Annotations or Fluent Api in OnModelCreating ?
Thnx for any help..
How do you specify a custom column name with a HasOne relationship in EF7?
Consider the following sample classes:
public class House
{
public int Id { get; set; }
public int BedroomCount { get; set; }
public Address Address { get; set; }
}
public class Address
{
public int Id { get; set; }
public string StreetName { get; set; }
public string StreetNumber { get; set; }
}
And this fluent configuration:
modelBuilder.Entity<House>()
.HasOne(x => x.Address)
.WithOne()
.OnDelete(DeleteBehavior.Cascade);
Which leads to this DB configuration:
CREATE TABLE [House] (
[Id] int NOT NULL IDENTITY,
[AddressId] int,
[BedroomCount] int NOT NULL,
CONSTRAINT [PK_House] PRIMARY KEY ([Id]),
CONSTRAINT [FK_House_Address_AddressId] FOREIGN KEY ([AddressId]) REFERENCES [Address] ([Id]) ON DELETE CASCADE);
CREATE TABLE [Address] (
[Id] int NOT NULL IDENTITY,
[StreetName] nvarchar(max),
[StreetNumber] nvarchar(max),
CONSTRAINT [PK_Address] PRIMARY KEY ([Id]));
How do I specify a column name other than "AddressId" on the House table? I cannot find a method similar to HasColumnName like there is on non-navigation properties.
I'm using Entity Framework 7 RC1-Final.
You can use Data Annotations to configure the foreign key of your relationship.
public int AddressID { get; set; }
[ForeignKey("AddressID")]
public Address Address { get; set; }
This requires a property that will be used as the foreign key in your relationship. Also, note that it is recommended that you have a explicit foreign key for your relationships other than a shadow foreign key. This will prevent you to have a lot of problems when inserting/updating since you don't need to set the entire navigation property Address to save a House entity. See the problem here
Not tested but perhaps this could work (can't find a way to install EF7 right now)
modelBuilder.Entity<House>()
.HasOne(x => x.Address)
.WithOne()
.OnDelete(DeleteBehavior.Cascade);
.HasForeignKey(x => x.AddressID);
You can check here for more examples: Foreign Key Relationships EF7
You can get property first from modelBuilder.Entity<House>().Metadata.GetProperties() list and then set its name
property.Relational().ColumnName = "YouCustomId"
This is my trial project using breeze/angular/EF. I don't understand why I get this error because I thought I had the same structure working before.
public class TshirtOrder
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<OrderItem> OrderItems { get; set; }
}
public class OrderItem
{
public int Id { get; set; }
[ForeignKey("Type")]
public int TshirtTypeId { get; set; }
public virtual TshirtType Type { get; set; }
[ForeignKey("Size")]
public int TshirtSizeId { get; set; }
public virtual TshirtSize Size { get; set; }
public double UnitPrice { get; set; }
public int Quantity { get; set; }
[ForeignKey("TshirtOrder")]
public int TshirtOrderId { get; set; }
public TshirtOrder TshirtOrder { get; set; }
}
The table definition looks like this:
CREATE TABLE [dbo].[TshirtOrder] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Name] NVARCHAR (MAX) NULL,
CONSTRAINT [PK_dbo.TshirtOrder] PRIMARY KEY CLUSTERED ([Id] ASC)
);
CREATE TABLE [dbo].[OrderItem] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[TshirtTypeId] INT NOT NULL,
[TshirtSizeId] INT NOT NULL,
[UnitPrice] FLOAT (53) NOT NULL,
[Quantity] INT NOT NULL,
[TshirtOrderId] INT NOT NULL,
CONSTRAINT [PK_dbo.OrderItem] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_dbo.OrderItem_dbo.TshirtType_TshirtTypeId] FOREIGN KEY ([TshirtTypeId]) REFERENCES [dbo].[TshirtType] ([Id]) ON DELETE CASCADE,
CONSTRAINT [FK_dbo.OrderItem_dbo.TshirtSize_TshirtSizeId] FOREIGN KEY ([TshirtSizeId]) REFERENCES [dbo].[TshirtSize] ([Id]) ON DELETE CASCADE,
CONSTRAINT [FK_dbo.OrderItem_dbo.TshirtOrder_TshirtOrderId] FOREIGN KEY ([TshirtOrderId]) REFERENCES [dbo].[TshirtOrder] ([Id]) ON DELETE CASCADE
);
This is how it gets saved in Breeze datacontext:
function _createTshirtOrder() {
var order = manager.createEntity("TshirtOrder");
order.orderItems.push(createOrderItem(lookups.tshirtTypes[0], lookups.tshirtSizes[0], 10));
common.saveEntity(order);
return order;
function createOrderItem(type, size, unitPrice) {
var item = manager.createEntity("OrderItem");
item.type = type;
item.size = size;
item.unitPrice = unitPrice;
item.quantity = 0;
return item;
}
}
Here is the exact error:
{"The INSERT statement conflicted with the FOREIGN KEY constraint \"FK_dbo.OrderItem_dbo.TshirtOrder_TshirtOrderId\". The conflict occurred in database \"dbbb\", table \"dbo.TshirtOrder\", column 'Id'.\r\nThe statement has been terminated."}
So, where is the problem?
I don't know what your "saveEntity" method looks like but I'm guessing it calls
entityManager.saveChanges([order]);
If so, then the problem is that you are only saving the order and NOT the orderItem as well, because you told it to only save the one order. Breeze tracks any changes to the entityManager so a better solution is usually to just let Breeze figure it out for you. i.e.
entityManager.saveChanges(); or entityManager.saveChanges(null, ... );
Which will save all added, modified or deleted records in the entityManager.
Alternately you can specify all of the entities you want saved.
entityManager.saveChanges([order, orderItem1, orderItem2, ... ]);