我刚刚也不得不做同样的事情。这是我的解决方案(可能不是最好的方法,但至少相当优雅):
首先,创建一个接口,让所有实体都实现它,该接口继承自INotifyPropertyChanging。这用于连接一些扩展方法并保持我们的实现很好地分离。在我的情况下,该接口称为ISandboxObject:
public interface ISandboxObject : INotifyPropertyChanging
{
// This is just a marker interface for Extension Methods
}
接下来创建一个新的静态类,包含一个扩展方法来获取DataContext。这是通过查找附加到INotifyPropertyChanging.PropertyChanging事件的LINQ Change Tracker上的事件处理程序来实现的。一旦我们找到了变化跟踪器,就可以从那里获取DataContext:
/// <summary>
/// Obtain the DataContext providing this entity
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static DataContext GetContext(this ISandboxObject obj)
{
FieldInfo fEvent = obj.GetType().GetField("PropertyChanging", BindingFlags.NonPublic | BindingFlags.Instance);
MulticastDelegate dEvent = (MulticastDelegate)fEvent.GetValue(obj);
Delegate[] onChangingHandlers = dEvent.GetInvocationList();
// Obtain the ChangeTracker
foreach (Delegate handler in onChangingHandlers)
{
if (handler.Target.GetType().Name == "StandardChangeTracker")
{
// Obtain the 'services' private field of the 'tracker'
object tracker = handler.Target;
object services = tracker.GetType().GetField("services", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(tracker);
// Get the Context
DataContext context = services.GetType().GetProperty("Context").GetValue(services, null) as DataContext;
return context;
}
}
// Not found
throw new Exception("Error reflecting object");
}
实体类不应该意识到数据上下文,因为它只是表的一个映射,但是数据上下文知道所有实体和连接属性的相关信息。
由于实体关系,您可以通过父实体类链接到子表而不是通过数据上下文。
数据上下文类将在消耗实体的最后使用,我不认为实体需要了解上下文的情况。
如果您能描述具体场景,我们可以尝试其他方法。
基本上,您可以通过一些技巧来实现这一点。DataContext将StandardChangeTracker附加到您的实体:
DataContext context = null; object changeTracker = (from i in o1.GetInvocationList() where i.Target.GetType().FullName == "System.Data.Linq.ChangeTracker+StandardChangeTracker" select i.Target).FirstOrDefault(); if (changeTracker != null) // DataCOntext通过StandardChangeTracker跟踪我们的更改 { object services = Reflector.GetFieldValue(changeTracker, "services"); context = (DataContext)Reflector.GetFieldValue(services, "context"); }
其中Reflector.GetFieldValue等于
public static object GetFieldValue(object instance, string propertyName) { return instance.GetType().GetField(propertyName, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(instance); }
我完全明白你的意思。我们应该在实体的部分类中进行计算/验证,但如果实体没有访问数据上下文,则我们能做多少呢?例如,在我的SalesOrder对象中,每当“Ship To”地址更改时,SalesOrder需要查询数据库以查找是否适用于该州/邮政编码的税。我一直在为此而奋斗,但今天我崩溃了,采用了丑陋的方法,但目前为止还不错。基本上,我所做的就是在我的部分类中创建一个“Context”属性,并在创建实体时将其设置为数据上下文。
Partial Class SalesOrder
Private moContext As L2S_SalesOrdersDataContext
Friend Property Context() As L2S_SalesOrdersDataContext
Get
Return moContext
End Get
Set(ByVal value As L2S_SalesOrdersDataContext)
moContext = value
End Set
End Property
...
可能会因为你分离实体而有所不同。