我的数据库中有几个表,它们具有在插入和更新时设置的只读字段,即:AddDate(DateTime),AddUserName(string),LastModDate(DateTime),LastModUserName(string)。
所有具有这些值的表都已设置为从以下接口继承:
public interface IUserTrackTable
{
string AddUserName { get; set; }
DateTime AddDate { get; set; }
string LastModUserName { get; set; }
DateTime LastModDate { get; set; }
}
因此,我在Edit.aspx页面上有以下方法:
protected void DetailsDataSource_Updating(object sender, LinqDataSourceUpdateEventArgs e)
{
IUserTrackTable newObject = e.NewObject as IUserTrackTable;
if (newObject != null)
{
newObject.LastModUserName = User.Identity.Name;
newObject.LastModDate = DateTime.Now;
}
}
但是,当它到达此方法时,e.OriginalObject已经丢失了所有四个字段的值,因此在实际更新期间会抛出ChangeConflictException。我尝试将四个列名添加到Init事件处理程序中的DetailsView1.DataKeyNames数组中:
protected void Page_Init(object sender, EventArgs e)
{
// other things happen before this
var readOnlyColumns = table.Columns.Where(c => c.Attributes.SingleOrDefaultOfType<ReadOnlyAttribute>(ReadOnlyAttribute.Default).IsReadOnly).Select(c => c.Name);
DetailsView1.DataKeyNames = DetailsView1.DataKeyNames.Union<string>(readOnlyColumns).ToArray<string>();
DetailsView1.RowsGenerator = new CustomFieldGenerator(table, PageTemplates.Edit, false);
// other things happen after this
}
我试过让代码只发生在PostBack上,但仍然没有。对于如何获取所有列的值来进行往返,我很遗憾。
CustomFieldGenerator唯一处理ReadOnlyAttribute的事情,遵循C# Bits的详细信息。
更新:经过进一步调查后,这些值将进行DetailsView_ItemUpdating事件的往返。所有值都存在于e.OldValues字典中。但是,它们在到达LinqDataSource_Updating事件时就会丢失。
显然,存在使这些列不参与并发检查或涉及硬编码的其他方式的“解决方案”,但理想的解决方案是在需要时动态添加适当的信息,以使其保持为动态解决方案。
答案 0 :(得分:0)
我Drovani,我认为你想要数据审核(参见Steve Sheldon的A Method to Handle Audit Fields in LINQ to SQL),我会在EF4的模型中这样做,你可以这样做:
partial void OnContextCreated()
{
// Register the handler for the SavingChanges event.
this.SavingChanges += new EventHandler(context_SavingChanges);
}
private static void context_SavingChanges(object sender, EventArgs e)
{
// handle auditing
AuditingHelperUtility.ProcessAuditFields(objects.GetObjectStateEntries(EntityState.Added));
AuditingHelperUtility.ProcessAuditFields(objects.GetObjectStateEntries(EntityState.Modified), InsertMode: false);
}
internal static class AuditingHelperUtility
{
internal static void ProcessAuditFields(IEnumerable<Object> list, bool InsertMode = true)
{
foreach (var item in list)
{
IAuditable entity = item as IAuditable;
if (entity != null)
{
if (InsertMode)
{
entity.InsertedBy = GetUserId();
entity.InsertedOn = DateTime.Now;
}
entity.UpdatedBy = GetUserId();
entity.UpdatedOn = DateTime.Now;
}
}
}
}
遗憾的是,EF v1
无法做到这一点