我尝试测试 WPF、C# 和 EF 5 以开发桌面应用程序。当我执行 context.SaveChanges 时,出现以下异常:列名 Simulation_SimulationID 无效。我尝试了几个技巧,但我无法解决这个问题,一切似乎都是正确的。以下实体:
//Entity Echeance
public partial class Echeance : INotifyPropertyChanged
{
public long EheanceId { get; set; }
public byte EchNumber { get; set; }
public System.DateTime date { get; set; }
public Double principal { get; set; }
public Double interet { get; set; }
public byte isLoy1 { get; set; }
public long SimulationId { get; set; }
public virtual simulation simulation { get; set; }
//Attributs non mappés
public Double tva { get; set; }
public Double txtva { get; set; }
public Double horstaxe { get; set; }
public Double ttc { get; set; }
public Double amtfin { get; set; }
public Double encfin { get; set; }
//Constructeur avec numéro de loyer
public Echeance(byte nnloy)
{
EchNumber = nnloy;
date = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 25);
principal = 0.000;
interet = 0.000;
horstaxe = 0.000;
tva = 0.000;
ttc = 0.000;
isLoy1 = 0;
ttc = 0.000;
amtfin = 0.000;
encfin = 0.000;
}
//Constructeur sans paramètres avec valeurs par défaut
public Echeance()
{
EchNumber = 0;
date = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 25);
principal = 0.000;
interet = 0.000;
horstaxe = 0.000;
tva = 0.000;
ttc = 0.000;
isLoy1 = 0;
ttc = 0.000;
amtfin = 0.000;
encfin = 0.000;
}
//Propriété Numloy : numéro loyer
public byte NumLoy
{
get { return EchNumber; }
set
{
EchNumber = value;
OnPropertyChanged("Numloy");
}
}
public DateTime DateEcheance
{
get { return date; }
set
{
date = value;
OnPropertyChanged("DateEcheance");
}
}
public Double MontantPrincipal
{
get
{
return principal;
}
set
{
principal = value;
OnPropertyChanged("MontantPrincipal");
}
}
public Double MontantInteret
{
get
{
return interet;
}
set
{
interet = value;
OnPropertyChanged("MontantInteret");
}
}
public Double MontantHT
{
get
{
return horstaxe;
}
set
{
horstaxe = value;
OnPropertyChanged("MontantHT");
}
}
public Double MontantTVA
{
get
{
return tva;
}
set
{
tva = value;
OnPropertyChanged("MontantTVA");
}
}
public Double MontantTTC
{
get
{
return ttc;
}
set
{
ttc = value;
OnPropertyChanged("MontantTTC");
}
}
public byte FirstLoyer
{
get { return isLoy1; }
set
{
isLoy1 = value;
OnPropertyChanged("FirstLoyer");
}
}
public Double Encours
{
get { return encfin; }
set
{
encfin = value;
OnPropertyChanged("Encours");
}
}
public Double Amortfin
{
get { return amtfin; }
set
{
amtfin = value;
OnPropertyChanged("Amortfin");
}
}
public Double TauxTVA
{
get { return txtva; }
set
{
txtva = value;
OnPropertyChanged("TauxTVA");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(name));
}
}
//Entity simulation
public partial class simulation : INotifyPropertyChanged
{
public long SimulationId { get; set; }
public Double baseLocative { get; set; }
public Double txInt { get; set; }
public Double txVr { get; set; }
public Double Autofin { get; set; }
public byte echjour { get; set; }
public Byte duree { get; set; }
public System.DateTime echBegin { get; set; }
public Double loy1 { get; set; }
public Byte loy1_freq { get; set; }
public Double encfin { get; set; }
public Double loyer { get; set; }
public Double txtva { get; set; }
public Byte perio { get; set; }
public Double ratio { get; set; }
public virtual IList<Echeance> echeancier { get; set; }
//public virtual ICollection<Echeance> echeancier { get; set; }
//Non mappés
Double Totpri;
Double Totint;
Double Totht;
Double Tottva;
Double Totttc;
Double loyDuplicate;
Double _timbre;
//Constructeur sans paramètres
public simulation()
{
baseLocative = 0.000;
txInt = 0.000;
txVr = 0.000;
Autofin = 0.000;
echjour = 25;
duree = 36;
loyer = 0.000;
loy1 = 0.000;
loy1_freq =1;
perio = 1;
txtva = 18.000;
Totpri = 0.000;
Totint = 0.000;
Totht = 0.000;
Tottva = 0.000;
Totttc = 0.000;
loyDuplicate = 0.000;
_timbre = 0.000;
int y = DateTime.Today.Year;
int m = DateTime.Today.Month;
int djour = DateTime.Today.Day;
int j = 25;
if (djour > 25)
{
m = m + 1;
if (m > 12)
{
m = 1;
y = y + 1;
}
}
//Date française
CultureInfo culture = CultureInfo.CreateSpecificCulture("fr-FR");
DateTimeStyles styles = DateTimeStyles.None;
DateTime dd;
string datestring = j.ToString() + "/" + m.ToString() + "/" + y.ToString();
DateTime.TryParse(datestring, culture, styles, out dd );
echBegin = dd;
echeancier = new List<Echeance>();
}
//Constructeur avec paramètres
public simulation(Double bl, Double txi, Double txr, Double autofin, Byte jouech, Byte ldur, DateTime ech1, Double loy1mnt, Byte per,Double timbre)
{
baseLocative = bl;
txInt = txi;
txVr = txr;
perio = per;
Autofin = autofin;
echjour = jouech;
duree = ldur;
echBegin = ech1;
loy1 = loy1mnt;
loy1_freq = 1;
encfin = 0.000;
ratio = 0.000;
_timbre = timbre;
echeancier = new List<Echeance>();
}
//Propriété base locative
public Double Montant
{
get { return baseLocative; }
set
{
baseLocative = value;
OnPropertyChanged("Montant");
}
}
//Propriété Taux d'intérêts
public Double Txtint
{
get { return txInt; }
set
{
txInt = value;
OnPropertyChanged("Txtint");
}
}
//Propriété Taux valeur résiduelle
public Double Txtvr
{
get { return txVr; }
set
{
txVr = value;
OnPropertyChanged("Txtvr");
}
}
//Propriété Autofinancement
public Double Autofinancement
{
get { return Autofin; }
set
{
Autofin = value;
OnPropertyChanged("Autofinancement");
}
}
//Propriété Jour échéance
public Byte JourEcheance
{
get { return echjour; }
set
{
echjour = value;
OnPropertyChanged("JourEcheance");
}
}
//Propriété Jour échéance
public Byte DureeCtr
{
get { return duree; }
set
{
duree = value;
OnPropertyChanged("DureeCtr");
}
}
//Propriété Jour échéance
public DateTime BeginEch
{
get { return echBegin; }
set
{
echBegin = value;
OnPropertyChanged("BeginEch");
}
}
//Propriété Jour échéance
public Double Loyer
{
get { return loyer; }
set
{
loyer = value;
OnPropertyChanged("Loyer");
}
}
//Périodicté
public Byte Periodicite
{
get { return perio; }
set
{
perio = value;
OnPropertyChanged("Periodicite");
}
}
//Premier loyer
public Double FirstLoyer
{
get { return loy1; }
set
{
loy1 = value;
OnPropertyChanged("FirstLoyer");
}
}
public Double TxtTva
{
get { return txtva; }
set
{
txtva = value;
OnPropertyChanged("TxtTva");
}
}
//Nombre de répétition du premier loyer
public Byte FrequenceLoy1
{
get { return loy1_freq; }
set
{
loy1_freq = value;
OnPropertyChanged("FrequenceLoy1");
}
}
public Double TotalPri
{
get { return Totpri ; }
set
{
Totpri = value;
OnPropertyChanged("TotalPri");
}
}
public Double TotalInt
{
get { return Totint; }
set
{
Totint = value;
OnPropertyChanged("TotalInt");
}
}
public Double TotalHt
{
get { return Totht; }
set
{
Totht = value;
OnPropertyChanged("TotalHt");
}
}
public Double TotalTva
{
get { return Tottva; }
set
{
Tottva = value;
OnPropertyChanged("TotalTva");
}
}
public Double TotalTtc
{
get { return Totttc; }
set
{
Totttc = value;
OnPropertyChanged("TotalTtc");
}
}
public Double Encfin
{
get { return encfin; }
set
{
encfin = value;
OnPropertyChanged("Encfin");
}
}
public Double Ratio
{
get { return ratio; }
set
{
ratio = value;
OnPropertyChanged("Ratio");
}
}
public Double LoyForDuplicate
{
get
{
return loyDuplicate;
}
set
{
loyDuplicate = value;
OnPropertyChanged("LoyForDuplicate");
}
}
//public IList<Echeance> ListEcheances
public IList<Echeance> ListEcheances
{
get
{
return echeancier;
}
set
{
echeancier = value;
OnPropertyChanged("ListEcheance");
}
}
public Double Timbre
{
get
{
return _timbre;
}
set
{
_timbre = value;
OnPropertyChanged("Timbre");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
我的 dbContext :
public class MyContext : DbContext
{
ILogger _currentLog = null;
public DbSet<simulation> Simulations { get; set; }
public DbSet<Echeance> Echeances { get; set; }
public MyContext(string cnxString, ILogger logger)
: base(cnxString)
{
Database.SetInitializer<MyContext>(null);
_currentLog = logger;
if (_currentLog != null)
_currentLog.LogInfoMessage("Connexion établie.");
}
public MyContext(ILogger logger)
: base("name=dbleaseEntities")
{
// Database.SetInitializer<MyContext>(null);
_currentLog = logger;
if (_currentLog != null)
_currentLog.LogInfoMessage("Connexion établie.");
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
_currentLog.LogInfoMessage("Mapping en cours...");
try
{
modelBuilder.Configurations.Add(new SimulationMapping());
modelBuilder.Configurations.Add(new EcheanceMapping());
//************************************************************************************************************************
//Propriétés non mappées (à ignorer) pour l'entité simulation
//Autofinancement JourEcheance DureeCtr BeginEch Loyer Periodicite FirstLoyer TxtTva FrequenceLoy1 LoyForDuplicate Timbre
//Les propriétés à ignorer lors de mapping
//************************************************************************************************************************
_currentLog.LogInfoMessage("Ignorer les champs de l'entité simulation.");
modelBuilder.Entity<simulation>().Ignore(t => t.TotalPri);
modelBuilder.Entity<simulation>().Ignore(t => t.TotalInt);
modelBuilder.Entity<simulation>().Ignore(t => t.TotalHt);
modelBuilder.Entity<simulation>().Ignore(t => t.TotalTva);
modelBuilder.Entity<simulation>().Ignore(t => t.TotalTtc);
modelBuilder.Entity<simulation>().Ignore(t => t.Montant);
modelBuilder.Entity<simulation>().Ignore(t => t.Txtint);
modelBuilder.Entity<simulation>().Ignore(t => t.Txtvr);
modelBuilder.Entity<simulation>().Ignore(t => t.Autofinancement);
modelBuilder.Entity<simulation>().Ignore(t => t.JourEcheance);
modelBuilder.Entity<simulation>().Ignore(t => t.DureeCtr);
modelBuilder.Entity<simulation>().Ignore(t => t.BeginEch);
modelBuilder.Entity<simulation>().Ignore(t => t.Loyer);
modelBuilder.Entity<simulation>().Ignore(t => t.Periodicite);
modelBuilder.Entity<simulation>().Ignore(t => t.FirstLoyer);
modelBuilder.Entity<simulation>().Ignore(t => t.TxtTva);
modelBuilder.Entity<simulation>().Ignore(t => t.FrequenceLoy1);
modelBuilder.Entity<simulation>().Ignore(t => t.LoyForDuplicate);
modelBuilder.Entity<simulation>().Ignore(t => t.Ratio);
modelBuilder.Entity<simulation>().Ignore(t => t.Timbre);
modelBuilder.Entity<simulation>().Ignore(t => t.Encfin);
//************************************************************************************************************************
//Propriétés non mappées (à ignorer) pour l'entité Echeance
//NumLoy, DateEcheance, MontantPrincipal, MontantInteret, MontantHT, MontantTVA, MontantTTC, FirstLoyer, Encours, Amortfin, TauxTVA
//tva, txtva,horstaxe, ttc, amtfin, encfin
//************************************************************************************************************************
_currentLog.LogInfoMessage("Ignorer les champs de l'entité Echéance.");
modelBuilder.Entity<Echeance>().Ignore(t => t.NumLoy);
modelBuilder.Entity<Echeance>().Ignore(t => t.DateEcheance);
modelBuilder.Entity<Echeance>().Ignore(t => t.MontantPrincipal);
modelBuilder.Entity<Echeance>().Ignore(t => t.MontantInteret);
modelBuilder.Entity<Echeance>().Ignore(t => t.MontantHT);
modelBuilder.Entity<Echeance>().Ignore(t => t.MontantTVA);
modelBuilder.Entity<Echeance>().Ignore(t => t.MontantTTC);
modelBuilder.Entity<Echeance>().Ignore(t => t.FirstLoyer);
modelBuilder.Entity<Echeance>().Ignore(t => t.Encours);
modelBuilder.Entity<Echeance>().Ignore(t => t.Amortfin);
modelBuilder.Entity<Echeance>().Ignore(t => t.TauxTVA);
modelBuilder.Entity<Echeance>().Ignore(t => t.tva);
modelBuilder.Entity<Echeance>().Ignore(t => t.txtva);
modelBuilder.Entity<Echeance>().Ignore(t => t.horstaxe);
modelBuilder.Entity<Echeance>().Ignore(t => t.ttc);
modelBuilder.Entity<Echeance>().Ignore(t => t.amtfin);
modelBuilder.Entity<Echeance>().Ignore(t => t.encfin);
base.OnModelCreating(modelBuilder);
_currentLog.LogInfoMessage("Mapping terminée avec succès.");
}
catch (Exception ex)
{
_currentLog.LogException(ex);
throw ex;
}
}
使用 Fluent 代码映射:
public class EcheanceMapping : EntityTypeConfiguration<Echeance>
{
public EcheanceMapping()
{
this.HasKey(t => t.EheanceId);
this.ToTable("Echeance");
this.Property(t => t.EheanceId).HasColumnName("EheanceId").IsRequired()
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
this.Property(t => t.EchNumber).HasColumnName("EchNumber").IsRequired();
this.Property(t => t.date).HasColumnName("date").IsRequired();
this.Property(t => t.principal).HasColumnName("principal");
this.Property(t => t.interet).HasColumnName("interet");
this.Property(t => t.isLoy1).HasColumnName("isloy1").IsRequired();
this.Property(t => t.SimulationId).HasColumnName("simulationId").IsRequired();
this.HasRequired(t => t.simulation).WithMany(t => t.echeancier).HasForeignKey(d => new { d.SimulationId });
}
}
public class SimulationMapping : EntityTypeConfiguration<simulation>
{
public SimulationMapping()
{
this.HasKey(t => t.SimulationId);
this.ToTable("simulation");
this.Property(t => t.SimulationId)
.HasColumnName("SimulationId")
.IsRequired()
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
//.HasDatabaseGeneratedOption(new Nullable<DatabaseGeneratedOption>(DatabaseGeneratedOption.Identity));
this.Property(t => t.baseLocative).HasColumnName("Baselocative").IsRequired();
this.Property(t => t.txInt).HasColumnName("txInt").IsRequired();
this.Property(t => t.txVr).HasColumnName("txvr");
this.Property(t => t.Autofin).HasColumnName("Autofin");
this.Property(t => t.echjour).HasColumnName("echjour").IsRequired();
this.Property(t => t.duree).HasColumnName("duree").IsRequired();
this.Property(t => t.echBegin).HasColumnName("echBegin").IsRequired();
this.Property(t => t.loy1).HasColumnName("loy1");
this.Property(t => t.loy1_freq).HasColumnName("loy1_freq");
this.Property(t => t.encfin).HasColumnName("encfin");
this.Property(t => t.loyer).HasColumnName("loyer");
this.Property(t => t.txtva).HasColumnName("txtva");
this.Property(t => t.perio).HasColumnName("perio").IsRequired();
this.Property(t => t.ratio).HasColumnName("ratio");
}
}
我使用以下工作单元:
public class UnitOfWork : MyContext, IUnitOfWork, IQueryableUnitOfWork
{
private ILogger _logger;
public UnitOfWork(string cnxString, ILogger logger) : base(cnxString, logger)
{
}
public UnitOfWork(ILogger logger)
: base(logger)
{
_logger = logger;
}
//Marquer une entitié de type <T> comme nouveau dans le contexte
public void RegisterNew<T>(T item) where T : class
{
_logger.LogInfoMessage("Marquage d'une entitié [" + item.GetType().Name + "] comme nouveau.");
try
{
if (item != null)
{
base.Entry<T>(item).State = EntityState.Added;
_logger.LogInfoMessage("Marquage d'une entitié [" + item.GetType().Name + "] comme nouveau.");
}
else
_logger.LogInfoMessage("Entité nulle lors de marquage comme nouveau.");
}
catch (Exception ex)
{
_logger.LogException(ex);
throw ex;
}
}
//Marquer une entitié de type <T> comme modifiée dans le contexte
public void RegisterChanged<T>(T item) where T : class
{
base.Entry<T>(item).State = EntityState.Modified;
}
//Marquer une entitié de type <T> comme unchangé dans le contexte
public void RegisterUnChanged<T>(T item) where T : class
{
base.Entry<T>(item).State = EntityState.Unchanged;
}
//Marquer une entitié de type <T> comme supprimée dans le contexte
public void RegisterDeleted<T>(T item) where T : class
{
base.Entry<T>(item).State = EntityState.Deleted;
}
//Récupère du contexte le dbset du type <T>
public IDbSet<T> GetSet<T>() where T : class
{
return base.Set<T>();
}
public IQueryable<T> GetQueryableSet<T>() where T : class
{
return base.Set<T>();
}
public void Rollback()
{
base.ChangeTracker.Entries().ToList().ForEach(e => e.State = EntityState.Unchanged);
}
public void Commit()
{
try
{
base.SaveChanges();
}
catch (DbUpdateException e)
{
var innerEx = e.InnerException;
while (innerEx.InnerException != null)
innerEx = innerEx.InnerException;
throw new Exception(innerEx.Message);
}
catch (DbEntityValidationException e)
{
var sb = new StringBuilder();
foreach (var entry in e.EntityValidationErrors)
{
foreach (var error in entry.ValidationErrors)
{
sb.AppendLine(string.Format("{0}-{1}-{2}",
entry.Entry.Entity,
error.PropertyName,
error.ErrorMessage
));
}
}
throw new Exception(sb.ToString());
}
}
public void Attach<T>(T item) where T : class
{
base.Entry<T>(item).State = EntityState.Unchanged;
}
}
如您所见,它是一对多的关系:一个“模拟”必须对应一个或n个“Echeance”,而“Echeance”不能没有模拟而存在。SimulationId 是表“simulation”中的主键和表“echeance”中的外键,它是一个标识列(sql server 2008)。我使用 IList 而不是 ICollection,因为我想在 WPF 数据网格中编辑“echeance”列表,使用 ICollection 是不可能的。
现在,当我执行 uow.Commit() 时,我得到“无效的 colmun 名称 Simulation_SimulationID”。
欢迎您的帮助...谢谢。