是否有任何简单的方法可以访问linq2sql实体类中的DataContext
。
我正在尝试创建类似EntitySet
的内容,但我无法弄清EntitySet
如何访问创建实体对象的上下文。
我希望有一个常规的linq2sql实体类,让类可以访问创建它的DataContext
。我知道这是可能的,因为当你有一个带有主键的实体类时,linq2sql可以让你选择在不创建新DataContext
的情况下加载所有子项。
答案 0 :(得分:6)
我只需做同样的事情。这是我的解决方案(虽然可能不是最好的方法,但至少相当优雅):
首先,为所有实体创建一个接口,以实现从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");
}
现在你有了一个很好的扩展方法,可以从任何实现ISandboxObject的对象为你提供一个DataContext。在愤怒地使用它之前,请先对此进行更多错误检查!
答案 1 :(得分:3)
基本上没有。
EntitySet<T>
类具有由数据上下文分配的内部Source
属性,它是按需获取数据的方式。但是,数据类本身并没有类似的东西。
但是,我认为实体框架可以以强制对象层次结构为代价获得更多访问权限。
与Entity Framework不同,LINQ-to-SQL(按设计)可以与常规的,持久性无知的类一起使用 - 因此它不会假设它可以访问这种类型的数据。
答案 2 :(得分:1)
实体类不应该知道数据上下文,因为它只是表的映射,但数据上下文具有所有实体和连接属性的知识
由于实体关系而不是通过数据上下文,您可以通过父实体类链接到子表
数据上下文类将在消耗实体的末尾使用,我不认为实体需要知道上下文,
如果您可以告诉具体情况,我们可以尝试另一种方法。
答案 3 :(得分:0)
我确切地知道你的意思。我们应该在实体的部分类中进行计算/验证,但如果实体无法访问datacontext,那么我们可以做多少?例如,在我的SalesOrder对象中,每当“Ship To”地址发生变化时,SalesOrder都需要查询数据库以查明税收是否适用于该州/邮政编码。我已经打了一段时间,但是今天我崩溃了,并且采用了丑陋的方法,但到目前为止还很好。基本上我所做的就是在我的部分类中创建一个“Context”属性,并在创建实体时使用datacontext设置它。
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
...
YMMV,特别是如果你要分离你的实体。
答案 4 :(得分:0)
基本上,你可以通过一些黑客来做到这一点。 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 tracks our changes through 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); }