Из того, что я вижу, скрипт модели БД выглядит примерно так:
CREATE TABLE Subscription(
[SubscriptionId] [int] IDENTITY(1,1) NOT NULL,
--[FieldName1] [nchar](100) NULL,
--[FieldNameN] [nchar](100) NULL,
CONSTRAINT [PK_Subscription] PRIMARY KEY CLUSTERED
(
[SubscriptionId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE SubscriptionError(
[SubscriptionErrorId] [int] NOT NULL,
[SubscriptionId] [int] NULL,
--[FieldName1] [nchar](100) NULL,
--[FieldNameN] [nchar](100) NULL,
CONSTRAINT [PK_SubscriptionError] PRIMARY KEY CLUSTERED
(
[SubscriptionErrorId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
ALTER TABLE SubscriptionError WITH CHECK ADD CONSTRAINT [FK_SubscriptionError_Subscription] FOREIGN KEY([SubscriptionId])
REFERENCES Subscription ([SubscriptionId])
ALTER TABLE [dbo].[SubscriptionError] CHECK CONSTRAINT [FK_SubscriptionError_Subscription]
Который [SubscriptionErrorId]
является ключевым, но это не поле с автоматическим приращением, поэтому для one-to-many
реляционная модель должна быть такой, как показано ниже:
public partial class Subscription
{
public Subscription()
{
SubscriptionErrors = new HashSet<SubscriptionError>();
}
public int SubscriptionId { get; set; }
public virtual ICollection<SubscriptionError> SubscriptionErrors { get; set; }
}
и для SubscriptionError
:
public partial class SubscriptionError
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int SubscriptionErrorId { get; set; }
public int? SubscriptionId { get; set; }
public virtual Subscription Subscription { get; set; }
}
Это работает как брелок, но для one-to-one
или one-to-zero
отношений, которые SubscriptionError
для Subscription
не являются коллекциейи отношение должно быть определено свободно текущими API, как показано ниже:
modelBuilder.Entity<Subscription>()
.HasOptional(s => s.SubscriptionError)
.WithRequired(ad => ad.Subscription);
и модели:
public partial class Subscription
{
public Subscription()
{
}
public int SubscriptionId { get; set; }
public virtual SubscriptionError SubscriptionError { get; set; }
}
public partial class SubscriptionError
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int SubscriptionErrorId { get; set; }
public int? SubscriptionId { get; set; }
public virtual Subscription Subscription { get; set; }
}
, поэтому, пожалуйста, посмотрите на SubscriptionError
вашей БД и проверьте, какие свойствав любом случае установите для SubscriptionError
в соглашениях EF, когда будет найдено свойство Id pk
(SubscriptionErrorId заканчивается Id, а EF интерпретирует его как первичный ключ), он сконфигурирует этот столбец как идентификатор, который означает, что база данных генерирует значение для свойства ключа,например, auto SubscriptionErrorId
будет автоматически сопоставлен с ключом идентификации, и нет необходимости явно его украшать DatabaseGeneratedOption
, но здесь используется DatabaseGeneratedOption.None
, потому что этот ключ должен генерироваться прагмой кода
о вашей проблеме , когда мы определили отношение one-to-one
, это означает, что дочерний элемент не означает, что его родитель не существует, по этой причине внешний ключ является первичным ключом в этой ситуации.!!!для вашей модели для режима SubscriptionError
опора SubscriptionId
также является ключевой из-за отношения один к одному или нулю, если вы посмотрите на образец в здесь нет PK
в StudentAddress
в любом случае в вашей ситуации SubscriptionError
с автоматической генерацией SubscriptionErrorId
, если вы не определите PK
, вы получите
SubscriptionError: EntityType: EntitySet 'SubscriptionError'основан на типе' SubscriptionError ', для которого не определены ключи.
если вы определите этот столбец как ключ с порядком, например:
[Key, Column("SubscriptionErrorId", Order = 1)]
public int SubscriptionErrorId { get; set; }
[Key, Column("SubscriptionId", Order = 2)]
public int SubscriptionId { get; set; }
, вы также получите
Объекты в Model.SubscriptionError участвуют в отношениях Subscription_SubscriptionError.0 связанных 'Subscription_SubscriptionError_Source' были найдены.1 'Subscription_SubscriptionError_Source' ожидается. '
, но если ваша модель выглядит примерно так, как указано ниже, определите SubscriptionErrorId
как Identity
и определите SubscriptionId
как ключ, который SubscriptionErrorId
является автоматическимприращение:
public partial class SubscriptionError
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int SubscriptionErrorId { get; set; }
[Key]
public int SubscriptionId { get; set; }
public virtual Subscription Subscription { get; set; }
}
тогда ваш код будет работать как брелок:
using (var context = new DbContext())
{
var se = new SubscriptionError()
{
FieldName1 = "Value",
SubscriptionId = 1,//Parent key
//SubscriptionErrorId is auto
};
context.SubscriptionError1.Add(se);
context.SaveChanges();
}