- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在对父集合执行 SQL 选择时,其中包含一项的子集合被延迟加载后,随后会为该子集合执行更新语句 - 无需显式调用更新。
父映射:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="ParentEntity"
assembly="ParentEntity">
<class name="ParentEntity" table="ParentEntity">
<id name="Id" column="ParentEntityId" unsaved-value="-1">
<generator class="identity"/>
</id>
<bag name="addresses" access="field" inverse="true" cascade="all-delete-orphan" where="IsDeleted = 0">
<key column="ParentEntityId"/>
<one-to-many class="Address"/>
</bag>
</class>
</hibernate-mapping>
实现:
public class ParentEntity : IEntity<ParentEntity>, IAuditableEntity, IDeletableEntity
{
private ICollection<Address> addresses;
protected ParentEntity()
{
addresses = new List<Address>();
}
public virtual ICollection<Address> Addresses
{
get
{
return new List<Address>(addresses.Where(a => !a.IsDeleted && !a.Validity.IsExpired)).AsReadOnly();
}
private set
{
addresses = value;
}
}
public virtual ICollection<Address> ExpiredAddresses
{
get
{
return new List<Address>(addresses.Where(a => !a.IsDeleted && a.Validity.IsExpired)).AsReadOnly();
}
}
#region IAuditableEntity Members
public virtual EntityTimestamp Timestamp
{
get { return timestamp; }
set { timestamp = value; }
}
#endregion
public virtual bool AddAddress(Address address)
{
if (addresses.Contains(address) || ExpiredAddresses.Contains(address) )
return false;
address.ParentEntity = this;
addresses.Add(address);
return true;
}
public virtual bool RemoveAddress(Address address)
{
if (!addresses.Contains(address) && !ExpiredAddresses.Contains(address))
return false;
address.IsDeleted = true;
return true;
}
}
子映射:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="..."
assembly="...">
<class name="Address" table="Address">
<id name="Id" column="AddressId" unsaved-value="-1">
<generator class="identity"/>
</id>
<property name="Street" ></property>
<property name="StreetNumber" ></property>
<property name="PostOfficeBox" ></property>
<property name="IsDeleted" not-null="true" ></property>
<many-to-one name="City" not-null="true" column="CityId" lazy="false" cascade="none" fetch="join" class="City"></many-to-one>
<many-to-one name="Type" not-null="true" column="AddressTypeId" lazy="false" cascade="none" fetch="join" class="AddressType"></many-to-one>
<many-to-one name="ParentEntity" not-null="true" update="false" column="ParentEntityId" lazy="false" cascade="none" fetch="join" class="ParentEntity"></many-to-one>
<component name="Timestamp" class="EntityTimestamp">
<property name="CreatedOn" not-null="true" />
<component name="CreatedBy" class="User">
<property name="Name" not-null="true" column="CreatedBy" />
</component>
<property name="ChangedOn" not-null="true" />
<component name="ChangedBy" class="User">
<property name="Name" not-null="true" column="ChangedBy" />
</component>
</component>
</class>
</hibernate-mapping>
子实现:
public class Address : IEntity<Address>, IAuditableEntity, IDeletableEntity
{
// id etc...
private EntityTimestamp timestamp;
private City city;
private bool isDeleted;
private string street;
private string postOfficeBox;
private string streetNumber;
private Validity validity;
private AddressType type;
private ParentEntity parentEntity;
public virtual EntityTimestamp Timestamp
{
get { return timestamp; }
set { timestamp = value; }
}
public virtual bool IsDeleted
{
get { return isDeleted; }
set { isDeleted = value; }
}
public virtual string Street
{
get { return street; }
set { street = value; }
}
public virtual string StreetNumber
{
get { return streetNumber; }
set { streetNumber = value; }
}
public virtual string PostOfficeBox
{
get { return postOfficeBox; }
set { postOfficeBox = value; }
}
public virtual City City
{
get { return city; }
set { city = value; }
}
public virtual AddressType Type
{
get { return type; }
set { type = value; }
}
public virtual Validity Validity
{
get { return validity; }
set { validity = value; }
}
protected internal virtual ParentEntity ParentEntity
{
get { return parentEntity; }
set { parentEntity = value; }
}
protected Address()
{
}
public Address(Validity validity)
{
this.validity = validity;
}
}
实体时间戳如下所示:
公共(public)类 EntityTimestamp : IValueObject{ private DateTime createdOn;
public virtual DateTime CreatedOn
{
get { return createdOn; }
private set { createdOn = value; }
}
private IUser createdBy;
public virtual IUser CreatedBy
{
get { return createdBy; }
private set { createdBy = value; }
}
private DateTime changedOn;
public virtual DateTime ChangedOn
{
get { return changedOn; }
private set { changedOn = value; }
}
private IUser changedBy;
public virtual IUser ChangedBy
{
get { return changedBy; }
private set { changedBy = value; }
}
protected EntityTimestamp()
{
}
private EntityTimestamp(DateTime createdOn, IUser createdBy, DateTime changedOn, IUser changedBy)
{
if (createdBy == null)
throw new ArgumentException("Created by user is null.");
if (changedBy == null)
throw new ArgumentException("Changed by user is null.");
this.createdOn = createdOn;
this.createdBy = createdBy;
this.changedBy = changedBy;
this.changedOn = changedOn;
}
public static EntityTimestamp New()
{
return new EntityTimestamp(new DateTimePrecise().Now, SecurityService.Current.GetCurrentUser(), new DateTimePrecise().Now, SecurityService.Current.GetCurrentUser());
}
public static EntityTimestamp New(IUser forUser)
{
return new EntityTimestamp(new DateTimePrecise().Now, forUser, new DateTimePrecise().Now, forUser);
}
public static EntityTimestamp NewUpdated(IUser forUser, EntityTimestamp oldTimestamp)
{
return new EntityTimestamp(oldTimestamp.CreatedOn, oldTimestamp.CreatedBy, new DateTimePrecise().Now, forUser);
}
public static EntityTimestamp NewUpdated(EntityTimestamp oldTimestamp)
{
return new EntityTimestamp(oldTimestamp.CreatedOn, oldTimestamp.CreatedBy, new DateTimePrecise().Now, SecurityService.Current.GetCurrentUser());
}
时间戳在事件监听器中设置:
public class EntitySaveEventListener : NHibernate.Event.Default.DefaultSaveEventListener
{
protected override object PerformSaveOrUpdate(SaveOrUpdateEvent e)
{
if (e.Entity is IAuditableEntity)
{
var entity = e.Entity as IAuditableEntity;
//todo: CascadeBeforeSave();
if (entity != null)
{
IsDirtyEntity(e.Session, e.Entity);
if (entity.IsNew)
{
entity.Timestamp = EntityTimestamp.New();
}
else
{
entity.Timestamp = EntityTimestamp.NewUpdated(entity.Timestamp);
}
}
}
return base.PerformSaveOrUpdate(e);
}
因此,当对父级执行 SQL 选择时,会执行地址实体的更新。
通过使用另一种方法,我已经检查了在自动更新之前传递给事件监听器的地址是否脏了。但是所有的 Prop 似乎都是一样的。
那会是什么?您需要更多信息吗?
我在更新时检查地址是否脏的方法:
public static Boolean IsDirtyEntity(ISession session, Object entity)
{
String className = NHibernateProxyHelper.GuessClass(entity).FullName;
ISessionImplementor sessionImpl = session.GetSessionImplementation();
IPersistenceContext persistenceContext = sessionImpl.PersistenceContext;
IEntityPersister persister = sessionImpl.Factory.GetEntityPersister(className);
EntityEntry oldEntry = sessionImpl.PersistenceContext.GetEntry(entity);
if ((oldEntry == null) && (entity is INHibernateProxy))
{
INHibernateProxy proxy = entity as INHibernateProxy;
Object obj = sessionImpl.PersistenceContext.Unproxy(proxy);
oldEntry = sessionImpl.PersistenceContext.GetEntry(obj);
}
Object [] oldState = oldEntry.LoadedState;
Object [] currentState = persister.GetPropertyValues(entity, sessionImpl.EntityMode);
Int32 [] dirtyProps = persister.FindDirty(currentState, oldState, entity, sessionImpl);
return (dirtyProps != null);
}
nhibernate sql调试:
// parent entity select
NHibernate.SQL: 2010-02-17 16:18:39,357 [21] DEBUG NHibernate.SQL [(null)] - SELECT * FROM ( SELECT spr.*, spft.[Rank], ROW_NUMBER() OVER (ORDER BY spft.[Rank] DESC) AS RowNum FROM CONTAINSTABLE(ParentEntitySpecialTable, Computed, '"some text"') AS spft INNER JOIN ParentEntity spr ON spr.ParentEntityId = spft.[Key]
) AS Results
WHERE
RowNum BETWEEN (@p0 - 1) * @p1 + 1 AND @p2 * @p3
ORDER BY
[Rank] DESC;@p0 = 1, @p1 = 20, @p2 = 1, @p3 = 20NHibernate.SQL: 2010-02-17 16:18:39,513 [21] DEBUG NHibernate.SQL [(null)] - SELECT addresses0_.ParentEntityId as ServiceP8_3_, addresses0_.AddressId as AddressId3_, addresses0_.AddressId as AddressId11_2_, addresses0_.Street as Street11_2_, addresses0_.StreetNumber as StreetNu3_11_2_, addresses0_.PostOfficeBox as PostOffi4_11_2_, addresses0_.IsDeleted as IsDeleted11_2_, addresses0_.CityId as CityId11_2_, addresses0_.AddressTypeId as AddressT7_11_2_, addresses0_.ParentEntityId as ServiceP8_11_2_, addresses0_.ValidityPeriodFrom as Validity9_11_2_, addresses0_.ValidityPeriodTo as Validit10_11_2_, addresses0_.CreatedOn as CreatedOn11_2_, addresses0_.CreatedBy as CreatedBy11_2_, addresses0_.ChangedOn as ChangedOn11_2_, addresses0_.ChangedBy as ChangedBy11_2_, city1_.CityId as CityId9_0_, city1_.IsDeleted as IsDeleted9_0_, city1_.Name as Name9_0_, city1_.ZipCode as ZipCode9_0_, city1_.CountryId as CountryId9_0_, city1_.CreatedOn as CreatedOn9_0_, city1_.CreatedBy as CreatedBy9_0_, city1_.ChangedOn as ChangedOn9_0_, city1_.ChangedBy as ChangedBy9_0_, addresstyp2_.AddressTypeId as AddressT1_6_1_, addresstyp2_.IsDeleted as IsDeleted6_1_, addresstyp2_.IsSystemDefault as IsSystem3_6_1_, addresstyp2_.Name as Name6_1_, addresstyp2_.[Key] as column5_6_1_, addresstyp2_.CreatedOn as CreatedOn6_1_, addresstyp2_.CreatedBy as CreatedBy6_1_, addresstyp2_.ChangedOn as ChangedOn6_1_, addresstyp2_.ChangedBy as ChangedBy6_1_ FROM Address addresses0_ inner join City city1_ on addresses0_.CityId=city1_.CityId inner join AddressType addresstyp2_ on addresses0_.AddressTypeId=addresstyp2_.AddressTypeId WHERE (addresses0_.IsDeleted = 0) and addresses0_.ParentEntityId=@p0;@p0 = 345625 'aspnet_wp.exe' (Managed): Loaded 'CountryProxyAssembly' 'aspnet_wp.exe' (Managed): Loaded 'CountryProxyModule'
// address is updated
NHibernate.SQL:
2010-02-17 16:18:51,607 [21] DEBUG NHibernate.SQL [(null)] - Batch commands: command 0:UPDATE Address SET Street = @p0, StreetNumber = @p1, PostOfficeBox = @p2, IsDeleted = @p3, CityId = @p4, AddressTypeId = @p5, ValidityPeriodFrom = @p6, ValidityPeriodTo = @p7, CreatedOn = @p8, CreatedBy = @p9, ChangedOn = @p10, ChangedBy = @p11 WHERE AddressId = @p12;@p0 = 'fff', @p1 = ' ', @p2 = NULL, @p3 = False, @p4 = 116644, @p5 = 1, @p6 = 20.01.2010 17:28:15, @p7 = 31.12.9999 00:00:00, @p8 = 20.01.2010 17:29:52, @p9 = 'fff', @p10 = 17.02.2010 16:18:51, @p11 = 'fff', @p12 = 117390
// address is updated
NHibernate.SQL:
2010-02-17 16:19:03,748 [21] DEBUG NHibernate.SQL [(null)] - Batch commands: command 0:UPDATE Address SET Street = @p0, StreetNumber = @p1, PostOfficeBox = @p2, IsDeleted = @p3, CityId = @p4, AddressTypeId = @p5, ValidityPeriodFrom = @p6, ValidityPeriodTo = @p7, CreatedOn = @p8, CreatedBy = @p9, ChangedOn = @p10, ChangedBy = @p11 WHERE AddressId = @p12;@p0 = 'fff', @p1 = ' ', @p2 = NULL, @p3 = False, @p4 = 116644, @p5 = 1, @p6 = 20.01.2010 17:28:15, @p7 = 31.12.9999 00:00:00, @p8 = 20.01.2010 17:29:52, @p9 = 'fff', @p10 = 17.02.2010 16:19:03, @p11 = 'fff', @p12 = 117390
最佳答案
我遇到了几乎相同的问题。我创建了非空字段和允许空值的更新字段。看起来你的两个都为非空,所以你可以简单地设置更新的字段,我在下面设置创建的字段。
我混合使用事件监听器。我不能使用 PreInsert 事件来填充“创建的”字段,因为它发生在处理的后期,并且在 PreInsert 触发之前我得到空检查错误。我使用 PreUpdate 事件是因为我找不到可靠的方法来判断实体是否真的脏了,如果我在 OnSaveOrUpdate 中设置“last_updated”字段,它肯定会使实体变脏并强制每次发布更新。通过使用 PreUpdate,我已经让 NHibernate 检查脏了,我只是在更新触发之前注入(inject)我的值。
查看此 ayende blog有关 PreUpdate 的更多信息
public class AuditableEventListener : DefaultSaveOrUpdateEventListener, IPreUpdateEventListener
{
public override void OnSaveOrUpdate(SaveOrUpdateEvent @event)
{
Auditable a = @event.Entity as Auditable;
if (a != null)
{
if (this.GetEntityState(@event.Entity, @event.EntityName, @event.Entry, @event.Session) == EntityState.Transient)
{
a.create_dt = DateTime.Now;
a.create_by = @event.Session.Load<Staff>(CurrentStaff.Id);
}
}
base.OnSaveOrUpdate(@event);
}
#region IPreUpdateEventListener Members
public bool OnPreUpdate(PreUpdateEvent @event)
{
var audit = @event.Entity as Auditable;
if (audit == null) return false;
var now = DateTime.Now;
var user = @event.Session.Load<Staff>(CurrentStaff.Id);
//Very important to keep the State and Entity synced together
Set(@event.Persister, @event.State, "last_update_dt", now);
Set(@event.Persister, @event.State, "last_update_by", user);
audit.last_update_dt = now;
audit.last_update_by = user;
return false;
}
#endregion
private void Set(IEntityPersister persister, object[] state, string propertyName, object value)
{
var index = Array.IndexOf(persister.PropertyNames, propertyName);
if (index == -1)
return;
state[index] = value;
}
}
然后确保连接到所需的事件监听器...
ISaveOrUpdateEventListener[] saveUpdateListeners = new ISaveOrUpdateEventListener[] { new AuditableEventListener() };
conf.EventListeners.SaveEventListeners = saveUpdateListeners;
conf.EventListeners.SaveOrUpdateEventListeners = saveUpdateListeners;
conf.EventListeners.UpdateEventListeners = saveUpdateListeners;
conf.EventListeners.PreUpdateEventListeners = new IPreUpdateEventListener[] { new AuditableEventListener() };
关于c# - NHibernate - 没有显式更新的意外更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2281924/
我查看了网站上的一些问题,但还没有完全弄清楚我做错了什么。我有一些这样的代码: var mongoose = require('mongoose'), db = mongoose.connect('m
基本上,根据 this bl.ocks,我试图在开始新序列之前让所有 block 都变为 0。我认为我需要的是以下顺序: 更新为0 退出到0 更新随机数 输入新号码 我尝试通过添加以下代码块来遵循上述
我试图通过使用随机数在循环中设置 JSlider 位置来模拟“赛马”的投注结果。我的问题是,当然,我无法在线程执行时更新 GUI,因此我的 JSlider 似乎没有在竞赛,它们从头到尾都在运行。我尝试
该功能非常简单: 变量:$table是正在更新的表$fields 是表中的字段,$values 从帖子生成并放入 $values 数组中而$where是表的索引字段的id值$indxfldnm 是索引
让我们想象一个环境:有一个数据库客户端和一个数据库服务器。数据库客户端可以是 Java 程序或其他程序等;数据库服务器可以是mysql、oracle等。 需求是在数据库服务器上的一个表中插入大量记录。
在我当前的应用程序中,我正在制作一个菜单结构,它可以递归地创建自己的子菜单。然而,由于这个原因,我发现很难也允许某种重新排序方法。大多数应用程序可能只是通过“排序”列进行排序,但是在这种情况下,尽管这
Provisioning Profile 有 key , key 链依赖于它。我想知道 key 什么时候会改变。 Key will change after renew Provisioning Pr
截至目前,我在\server\publications.js 中有我的 MongoDB“选择”,例如: Meteor.publish("jobLocations", function () { r
我读到 UI 应该始终在主线程上更新。但是,当谈到实现这些更新的首选方法时,我有点困惑。 我有各种函数可以执行一些条件检查,然后使用结果来确定如何更新 UI。我的问题是整个函数应该在主线程上运行吗?应
我在代理后面,我无法构建 Docker 镜像。 我试过 FROM ubuntu , FROM centos和 FROM alpine ,但是 apt-get update/yum update/apk
我构建了一个 Java 应用程序,它向外部授权客户端公开网络服务。 Web 服务使用带有证书身份验证的 WS-security。基本上我们充当自定义证书颁发机构 - 我们在我们的服务器上维护一个 ja
因此,我有时会在上传新版本时使用 app_offline.htm 使应用程序离线。 但是,当我上传较大的 dll 时,我收到黄色错误屏幕,指出无法加载 dll。 这似乎与我对 app_offline.
我刚刚下载了 VS Apache Cordova Tools Update 5,但遇到了 Node 和 NPM 的问题。我使用默认的空白 cordova 项目进行测试。 版本 如果我在 VS 项目中对
所以我有一个使用传单库实例化的 map 对象。 map 实例在单独的模板中创建并以这种方式路由:- var app = angular.module('myApp', ['ui', 'ngResour
我使用较早的 Java 6 u 3 获得的帧速率是新版本的两倍。很奇怪。谁能解释一下? 在 Core 2 Duo 1.83ghz 上,集成视频(仅使用一个内核)- 1500(较旧的 java)与 70
我正在使用 angular 1.2 ng-repeat 创建的 div 也包含 ng-click 点击时 ng-click 更新 $scope $scope 中的变化反射(reflect)在使用 $a
这些方法有什么区别 public final void moveCamera(CameraUpdate更新)和public final void animateCamera (CameraUpdate
我尝试了另一篇文章中某人评论中关于如何将树更改为列表的建议。但是,我在某处(或某物)有未声明的变量,所以我列表中的值是 [_G667, _G673, _G679],而不是 [5, 2, 6],这是正确
实现以下场景的最佳方法是什么? 我需要从java应用程序调用/查询包含数百万条记录的数据库表。然后,对于表中的每条记录,我的应用程序应该调用第三方 API 并获取状态字段作为响应。然后我的应用程序应该
只是在编写一些与 java 图形相关的代码,这是我今天的讲座中的非常简单的示例。不管怎样,互联网似乎说更新不会被系统触发器调用,例如调整框架大小等。在这个例子中,更新是由这样的触发器调用的(因此当我只
我是一名优秀的程序员,十分优秀!