如何在旧数据库中映射表继承?
我发现映射遗留数据库非常困难。
场景如下:承包商申请新许可证。查询并显示License。承包商修改任何需要修改的信息。完成后,应用程序将保存到数据库中。
许可证属于企业或所有者,这是任何多态关联的许可证。许可证本身拥有用于建立关联的TableID 和RecordID。
许可证有许多应用程序。该系统中有多种类型的应用程序,因此有一个“ApplicationCommon”表和一个“LicenseApplication”表。这个特定的应用程序是一个许可证。 ApplicationCommon 和 LicenseApplication 共享相同的主密钥。换句话说,ApplicationCommon id 与 LicenseApplication id 相同。这就是表继承(或者我认为是这样)。
由于与业务的奇怪的多态关联,我必须与许可证分开查询业务数据(或者我认为,这对 nHibernate 来说有点新鲜)。一旦我获得了许可证和业务,我就会尝试提出新的申请,那就是系统出现故障的时候。
这是我得到的例外:
"object references an unsaved transient instance - save the transient instance
before flushing. Type: LicenseApplication, Entity: LicenseApplication"
这是映射:
public LicenseApplicationMap()
{
Table("Applications_LicenseApplication");
Id(x => x.ID).Column("intApplicationID").Not.Nullable();
Map(x => x.TableID).Column("intTableID").Nullable();
Map(x => x.RecordID).Column("intRecordID").Nullable();
References(x => x.Type).Column("intLicenseTypeID").Not.Nullable();
Map(x => x.InsuranceExpiresOn).Column("dtInsuranceExpiresOn");
Map(x => x.WCInsuranceExpiresOn).Column("dtWCInsuranceExpiresOn");
Map(x => x.Updated).Column("dtUpdated");
Map(x => x.AuthorizedRepresentativeFirstName).Column("strAuthRepFirstName");
Map(x => x.AuthorizedRepresentativeLastName).Column("strAuthRepLastName");
Map(x => x.AuthorizedRepresentativeGreeting).Column("strAuthRepGreeting");
HasOne(x => x.ApplicationCommon).ForeignKey("intApplicationID").Cascade.All();
References(x => x.License).Column("intLicenseID");
HasMany(x => x.Officers).KeyColumn("intApplicationID");
HasMany(x => x.Designees).KeyColumn("intApplicationID");
}
。
public LicenseCommonMap()
{
Table("Licensing_LicenseCommon");
Id(x => x.ID).Column("intLicenseID").Not.Nullable();
Map(x => x.TableID).Column("intTableID").Nullable();
Map(x => x.RecordID).Column("intRecordID").Nullable();
Map(x => x.LicenseNumber).Column("strNumber");
References(x => x.Type).Column("intLicenseTypeID").Not.Nullable();
References(x => x.Status).Column("intLicenseStatusID").Not.Nullable();
Map(x => x.StartsOn).Column("dtStartsOn");
Map(x => x.EndsOn).Column("dtEndsOn");
Map(x => x.CreatedOn).Column("dtCreatedOn");
Map(x => x.RenewedOn).Column("dtRenewedOn");
Map(x => x.InsuranceExpiresOn).Column("dtInsuranceExpiresOn");
Map(x => x.WorkmansCompensationExpiresOn).Column("dtWCInsuranceExpiresOn");
Map(x => x.LastUpdated).Column("dtLastUpdated");
HasMany(x => x.Applications).KeyColumn("intLicenseID");
}
。
public ApplicationCommonMap()
{
Table("Applications_ApplicationCommon");
Id(x => x.ID).Column("intApplicationID");
References(x => x.Type).Column("intApplicationTypeID");
References(x => x.Status).Column("intApplicationStatusID");
References(x => x.LicenseApplication).Column("intApplicationID").Cascade.All();
}
。
public BusinessMap()
{
Table("Core_Business");
Id(x => x.ID).Column("intBusinessID").GeneratedBy.Identity();
Map(x => x.BusinessName).Column("strBusinessName").Not.Nullable();
Map(x => x.PhoneNumber).Column("strPhoneNumber").Not.Nullable();
Map(x => x.FaxNumber).Column("strFaxNumber").Not.Nullable();
Map(x => x.EmailAddress).Column("strEmailAddress").Not.Nullable();
Map(x => x.YearOrganized).Column("strYearOrganized").Not.Nullable();
Map(x => x.LastUpdated).Column("dtLastUpdated").Not.Nullable();
Map(x => x.PhysicalAddr1).Column("strPhysicalAddr1").Not.Nullable();
Map(x => x.PhysicalAddr2).Column("strPhysicalAddr2").Nullable();
Map(x => x.PhysicalCity).Column("strPhysicalCity").Not.Nullable();
Map(x => x.PhysicalState).Column("strPhysicalState").Not.Nullable();
Map(x => x.PhysicalCountry).Column("strPhysicalCountry").Not.Nullable();
Map(x => x.PhysicalZip).Column("strPhysicalZip").Not.Nullable();
Map(x => x.MailingAddr1).Column("strMailingAddr1").Not.Nullable();
Map(x => x.MailingAddr2).Column("strMailingAddr2").Nullable();
Map(x => x.MailingCity).Column("strMailingCity").Not.Nullable();
Map(x => x.MailingState).Column("strMailingState").Not.Nullable();
Map(x => x.MailingCountry).Column("strMailingCountry").Not.Nullable();
Map(x => x.MailingZip).Column("strMailingZip").Not.Nullable();
}
最后,我使用 .Net MVC、AutoMapper 和 S#rpArch,所以这是我的控制器操作和查询。 SaveLicense 和 SaveQuery 执行相同的逻辑,SaveOrUpdate,然后 Flush。
[HttpPost]
[Transaction]
public ActionResult Edit(int id, LicenseViewModel applicationData)
{
// 1. Get the current license.
var license = _licenseService.GetLicenseCommon(id);
// 2. Make changes to license that where made during application process
Mapper.Map<LicenseViewModel , LicenseCommon>(applicationData, license);
var business = _licenseService.GetBusiness(license.RecordID);
Mapper.Map<LicenseViewModel , Business>(applicationData, business);
business.LastUpdated = DateTime.Now;
// 3. Create a new application and add it to the license
var application = new LicenseApplication();
Mapper.Map<LicenseViewModel , LicenseApplication>(applicationData, application);
application.Updated = DateTime.Now;
application.InsuranceExpiresOn = DateTime.Parse(applicationData.GeneralLiabilityExpiration);
application.WCInsuranceExpiresOn = DateTime.Parse(applicationData.WorkmansCompensationExpiration);
application.TableID = 33;
application.RecordID = license.RecordID;
// 4. Save the license and it's applications to the database.
license.Business = business; //Don't think this works at all...
license.Applications.Add(application);
application.License = license;
///////////////// BOOM THIS IS WHERE IT BLOWS UP //////////////////////
_licenseService.SaveLicense(license);
_businessService.SaveBusiness(business);
// 5. Convert the modified license and it's newly created application to an LicenseViewModel
Mapper.Map<LicenseCommon, LicenseViewModel >(license, applicationData);
// 6. return json or error message
return Json(applicationData);
}
请告诉我我的映射有什么问题。
I am finding it very difficult to map a legacy database.
Here is the scenario: A contractor applies for a new license. The license is queried and displayed. The contractor modifies any information that needs to be modified. And upon completion an application is saved to the database.
A license belongs to either a business or an owner, this is a one to any polymorphic association. The License itself holds a TableID and RecordID that are used to make the association.
Licenses have many Applications. There are several types of Applications in this System, so there is an "ApplicationCommon" table and an "LicenseApplication" table. This particular application is a for a license. The ApplicationCommon and The LicenseApplication share the same primary key. In other words the ApplicationCommon id is the same and the LicenseApplication id. So this is table inheritance (or so I think).
Because of the weird polymorphic association with the business, I have to query for the business data separately from the license (Or so I think, kind of new to nHibernate). Once I have the license and the business I try to make a new application, that is when the system fails.
Here is the exception that I get:
"object references an unsaved transient instance - save the transient instance
before flushing. Type: LicenseApplication, Entity: LicenseApplication"
Here are the mappings:
public LicenseApplicationMap()
{
Table("Applications_LicenseApplication");
Id(x => x.ID).Column("intApplicationID").Not.Nullable();
Map(x => x.TableID).Column("intTableID").Nullable();
Map(x => x.RecordID).Column("intRecordID").Nullable();
References(x => x.Type).Column("intLicenseTypeID").Not.Nullable();
Map(x => x.InsuranceExpiresOn).Column("dtInsuranceExpiresOn");
Map(x => x.WCInsuranceExpiresOn).Column("dtWCInsuranceExpiresOn");
Map(x => x.Updated).Column("dtUpdated");
Map(x => x.AuthorizedRepresentativeFirstName).Column("strAuthRepFirstName");
Map(x => x.AuthorizedRepresentativeLastName).Column("strAuthRepLastName");
Map(x => x.AuthorizedRepresentativeGreeting).Column("strAuthRepGreeting");
HasOne(x => x.ApplicationCommon).ForeignKey("intApplicationID").Cascade.All();
References(x => x.License).Column("intLicenseID");
HasMany(x => x.Officers).KeyColumn("intApplicationID");
HasMany(x => x.Designees).KeyColumn("intApplicationID");
}
.
public LicenseCommonMap()
{
Table("Licensing_LicenseCommon");
Id(x => x.ID).Column("intLicenseID").Not.Nullable();
Map(x => x.TableID).Column("intTableID").Nullable();
Map(x => x.RecordID).Column("intRecordID").Nullable();
Map(x => x.LicenseNumber).Column("strNumber");
References(x => x.Type).Column("intLicenseTypeID").Not.Nullable();
References(x => x.Status).Column("intLicenseStatusID").Not.Nullable();
Map(x => x.StartsOn).Column("dtStartsOn");
Map(x => x.EndsOn).Column("dtEndsOn");
Map(x => x.CreatedOn).Column("dtCreatedOn");
Map(x => x.RenewedOn).Column("dtRenewedOn");
Map(x => x.InsuranceExpiresOn).Column("dtInsuranceExpiresOn");
Map(x => x.WorkmansCompensationExpiresOn).Column("dtWCInsuranceExpiresOn");
Map(x => x.LastUpdated).Column("dtLastUpdated");
HasMany(x => x.Applications).KeyColumn("intLicenseID");
}
.
public ApplicationCommonMap()
{
Table("Applications_ApplicationCommon");
Id(x => x.ID).Column("intApplicationID");
References(x => x.Type).Column("intApplicationTypeID");
References(x => x.Status).Column("intApplicationStatusID");
References(x => x.LicenseApplication).Column("intApplicationID").Cascade.All();
}
.
public BusinessMap()
{
Table("Core_Business");
Id(x => x.ID).Column("intBusinessID").GeneratedBy.Identity();
Map(x => x.BusinessName).Column("strBusinessName").Not.Nullable();
Map(x => x.PhoneNumber).Column("strPhoneNumber").Not.Nullable();
Map(x => x.FaxNumber).Column("strFaxNumber").Not.Nullable();
Map(x => x.EmailAddress).Column("strEmailAddress").Not.Nullable();
Map(x => x.YearOrganized).Column("strYearOrganized").Not.Nullable();
Map(x => x.LastUpdated).Column("dtLastUpdated").Not.Nullable();
Map(x => x.PhysicalAddr1).Column("strPhysicalAddr1").Not.Nullable();
Map(x => x.PhysicalAddr2).Column("strPhysicalAddr2").Nullable();
Map(x => x.PhysicalCity).Column("strPhysicalCity").Not.Nullable();
Map(x => x.PhysicalState).Column("strPhysicalState").Not.Nullable();
Map(x => x.PhysicalCountry).Column("strPhysicalCountry").Not.Nullable();
Map(x => x.PhysicalZip).Column("strPhysicalZip").Not.Nullable();
Map(x => x.MailingAddr1).Column("strMailingAddr1").Not.Nullable();
Map(x => x.MailingAddr2).Column("strMailingAddr2").Nullable();
Map(x => x.MailingCity).Column("strMailingCity").Not.Nullable();
Map(x => x.MailingState).Column("strMailingState").Not.Nullable();
Map(x => x.MailingCountry).Column("strMailingCountry").Not.Nullable();
Map(x => x.MailingZip).Column("strMailingZip").Not.Nullable();
}
And finally, I am using .Net MVC, AutoMapper and S#rpArch, so here is my controller action, and my query. SaveLicense and SaveQuery bother perform the same logic, SaveOrUpdate, then Flush.
[HttpPost]
[Transaction]
public ActionResult Edit(int id, LicenseViewModel applicationData)
{
// 1. Get the current license.
var license = _licenseService.GetLicenseCommon(id);
// 2. Make changes to license that where made during application process
Mapper.Map<LicenseViewModel , LicenseCommon>(applicationData, license);
var business = _licenseService.GetBusiness(license.RecordID);
Mapper.Map<LicenseViewModel , Business>(applicationData, business);
business.LastUpdated = DateTime.Now;
// 3. Create a new application and add it to the license
var application = new LicenseApplication();
Mapper.Map<LicenseViewModel , LicenseApplication>(applicationData, application);
application.Updated = DateTime.Now;
application.InsuranceExpiresOn = DateTime.Parse(applicationData.GeneralLiabilityExpiration);
application.WCInsuranceExpiresOn = DateTime.Parse(applicationData.WorkmansCompensationExpiration);
application.TableID = 33;
application.RecordID = license.RecordID;
// 4. Save the license and it's applications to the database.
license.Business = business; //Don't think this works at all...
license.Applications.Add(application);
application.License = license;
///////////////// BOOM THIS IS WHERE IT BLOWS UP //////////////////////
_licenseService.SaveLicense(license);
_businessService.SaveBusiness(business);
// 5. Convert the modified license and it's newly created application to an LicenseViewModel
Mapper.Map<LicenseCommon, LicenseViewModel >(license, applicationData);
// 6. return json or error message
return Json(applicationData);
}
Please tell me what is wrong with my mappings.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
HasMany(x => x.Applications).KeyColumn("intLicenseID");
缺少.Cascade.All()
,因此保存许可证也会保存对应用程序的更改。并且
.Inverse
也可以很好地告诉 NH 应用程序负责关联。还有
HasMany(x => x.Applications).KeyColumn("intLicenseID");
is missing a.Cascade.All()
so saving the license also saves changes to Applications.And
.Inverse
would be good too to tell NH that Application is responsible for the association.And also