LINQ to SQL:常见问题解答(FAQ) [英] LINQ to SQL: Answers to Frequently asked Questions (FAQ)

查看:57
本文介绍了LINQ to SQL:常见问题解答(FAQ)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开始编译人们对LINQ to SQL的常见问题的答案列表我希望能帮助消除人们对如何使用它的误解。这就是我到目前为止...



问:如何在插入新实体时从数据库中获取默认值?


A:LINQ to SQL不支持使用数据库中的默认值。 使用SubmitChanges时实体中的值。 您可以通过实现插入来覆盖LINQ to SQL如何插入实体DataContext上的方法。 对于名为"Entity"的实体类型,实现一个签名为"InsertEntity(Entity instance)"的函数。



< font size = 3> Q: 如何附加和更新实体? 当我附加并调用SubmitChanges时发生。


A: 将实体附加到DataContext可能无法按预期工作。 附加实体仅等同于刚从数据库查询的实体尚未修改。 为了指示您想要更新实体的DataContext,您必须向其提供描述实体如何更改的信息。 您可以通过多种方式执行此操作。 1)您可以调用Attach将实体添加到DataContext,然后修改单个属性。 这假定实体尚未处于修改状态。 2)您可以调用Attach的形式,它接受当前和原始实例实体。 DataContext将识别各个属性值不同。 3)您可以调用另一个布尔值的Attach形式参数设置为true表示DataContext应将实体视为所有已修改的属性。 该选项要求对象具有版本属性。



问:如何使用.Net Remoting序列化实体?


A:LINQ to SQL不支持使用.Net Re进行序列化MotileRef和EntitySet等关键数据类型不可序列化。



问:如何使用WCF(Windows Communication Foundation)序列化实体?


A:LINQ to SQL通过生成WCF序列化属性和特殊序列化,支持通过WCF序列化为XML代码生成期间的特定逻辑。 您可以通过将序列化模式设置为"单向"来打开设计器中的此功能。 注意这是不是序列化的一般解决方案,因为单向模式可能不适用于许多用例。



问:如何在多层应用程序中的层之间移动实体?


A: 虽然可以使用WCF序列化在层之间移动实体,但它可能不足以满足您的应用需求不允许进行更改的往返。 将自定义数据交换合同定义为Web服务API的一部分是一个更好的全方位解决方案。



问:我应该在每个业务逻辑方法中创建一个新的DataContext吗?


A:DataContext符合工作单元设计模式。 除非您在每个操作之间的物理层之间移动数据,否则您应该在工作期间保持DataContext的活动状态。


< p class = MsoNormal style ="margin:0in 0in 10pt">


问:我应该将DataContext保存在静态/全局/共享变量中吗?


A:DataContext不是线程安全的并不意味着要共享。 DataContext用于单个单元或工作或最多 用于多个连续单元工作。



问:我应该把业务逻辑放在哪里? 我正在开发的系统在实体本身上使用静态方法进行加载,保存和其他操作。


A:DataContext符合工作单元设计模式。 工作环境必须存在并与实体本身保持独立。 您应该将所有业务逻辑作为方法放在DataContext上,或者设计一个单独的业务上下文apsulate一个DataContext实例。 你不应该使用静态方法。



问:LINQ to SQL实体是业务实体还是数据传输对象? 如何在LINQ to SQL之上构建业务层?


答:LINQ to SQL实体都是业务实体和数据传输对象。 LINQ to SQL取代了您的数据访问层,是您业务层的基础。 您可以添加业务直接逻辑到DataContext或将DataContext封装在您自己的业务环境中。 创建单独的业务环境的目的是限制对其他Da的访问taContext方法。 如果这对您来说不是问题,那么将所有业务逻辑方法放在DataContext上是最佳选择。



< b style =""> 问:如何将实体缓存超出单个DataContext的生命周期? 我想保留一个缓存中的实体集合,以便所有后续请求都可以从此缓存中读取,而不是每次都返回到数据库。


A:可以在单个DataContext的生命周期之外缓存实体。 但是,对于具有延迟加载属性的实体执行此操作是危险的,因为如果导航这些属性,您可能会访问原始DataContext。 您也可能无意中保留通过相同DataContext实现的所有实体,从而导致内存泄漏。 为了缓解这些问题,您可以转动延迟加载首次检索这些实体时关闭,或者可以在使用ToList或ToArray等操作完全加载实体后处理DataContext。



问:如何将实体重新附加到新的DataContext? 当我尝试这样做时,我会抛出异常。


A:LINQ to SQL不支持重新附加实体。 实体实际上从未脱离实体发起DataContexts。 Attach方法旨在与从另一个物理层往返数据后新创建的实体实例一起使用。 如果仍然卸载任何延迟属性,LINQ to SQL会检测到实体属于另一个DataContext。 可以欺骗DataContext接受来自另一个DataContext的实体,或者没有延迟属性,预先加载所有这些实体,或者在原始DataContext上关闭延迟加载。



问:如何使用全局缓存实体初始化新实体实例的关联属性或更改关联属性以进行更新? 当我尝试这个时,我会遇到奇怪的行为,例如我不想要的插入或者在SubmitChanges期间抛出异常。


A:LINQ to SQL不支持在同一对象图中混合和匹配从不同DataContext实例加载的实体。 尝试这样做通常是一个坏主意。 大多数关联属性都是双向的,因此将一个属性分配给另一个属性或将一个属性添加到集合属性会更改两个实体中的状态和引用。 这意味着全局缓存实体可能同时在多个线程上进行修改(作为服务运行时)。 作为一般经验法则,单个连接的实体图应该一次只与一个工作单元相关联。 使用从中检索的实体,而不是使用全局缓存的实体来分配关联属性。您用于执行插入或更新的DataContext,或直接为外键字段分配值以避免额外往返数据库服务器。


< font face = Arial size = 2>

解决方案

关于此......



问:我应该把业务逻辑放在哪里?我正在开发的系统在实体本身上使用静态方法进行加载,保存和其他操作。


A:DataContext符合工作单元设计模式。工作环境必须存在并与实体本身分开维护。您应该将所有业务逻辑作为方法放在DataContext上,或者设计一个封装DataContext实例的单独业务上下文。你不应该使用静态方法。



...请你在以下方面进一步展开...



(1)您如何"将所有业务逻辑作为方法放在DataContext上" ;?



例如,我们经常为在Linq上下文中注册的人创建部分类。然后,我们在每个实体中实现可扩展性方法,例如OnValidate。



首先,我们的方式看起来非常合理且做得对 - 把工作放在需要的对象附近验证,因为验证逻辑特定于该特定对象。为什么每个类的OnValidate可扩展性方法在生成的类中作为存根存在,如果不建议可以以自定义方式实现它们。 (这就是Scott Gu在他的Linq-To-Sql系列中所展示的,BTW。)



其次,如果这是"在DataContext上" (也许你的意思是"在...中"),这种实现是什么样的?是否意味着在DataContext上创建一个局部类,然后将类特定的验证逻辑放在那里?



你能解释一下吗? ?也许我读错了你?



(2)。关于"你不应该使用静态方法",我认为你的意思是不要创建"在实体本身上使用静态方法进行加载,保存和其他操作"的代码,如上面提出的问题。你为什么这么说?



为什么有一个静态方法,例如DeleteWithCustomCascade(long targetId)或者在Linq上下文中注册的表的部分类的自定义实现中是否存在IsExisting(long targetId)?这些方法,尤其是像IsExisiting这样的非动作查询,似乎无害,因为静态,似乎在我们的生产中工作得很好,并且在调用站点上不那么混乱。你能解释一下原因吗?


I'm starting to compile a list of answers to common questions people have with LINQ to SQL that I hope will help dispell misconceptions people have with how to use it.  This is what I've got so far...

 

Q: How do I get default values from the database when inserting new entities?

A: LINQ to SQL does not support using default values from the database.  The values in the entity at the time SubmitChanges is called are used instead.  You can override how LINQ to SQL inserts entities by implementing an insert method on the DataContext.  For an entity type called ‘Entity’ implement a function with the signature of ‘InsertEntity(Entity instance)’. 

 

Q:  How do I attach and update entities?  When I attach and call SubmitChanges nothing happens.

A:  Attaching entities to a DataContext may not work as you intend.  An attached entity is merely the equivalent of an entity that has just been queried from the database and not yet modified.  In order to instruct the DataContext that you intend to have the entity updated you must provide it with information describing how the entity has changed.  You can do this in a variety of ways.  1) You can call Attach to add the entity to the DataContext and then modify individual properties.  This assumes the entity is not already in a modified state.  2) You can call the form of Attach that takes both a current and original instance of the entity.  The DataContext will recognize that individual properties values differ.  3) You can call the form of Attach that takes an additional Boolean parameter set to true to indicate that the DataContext should treat the entity as all properties modified.  The option requires that the object have a version property.

 

Q: How do I serialize entities using .Net Remoting?

A: LINQ to SQL does not support serialization using .Net Remoting.  Key data types such as EntityRef and EntitySet are not serializable. 

 

Q: How do I serialize entities using WCF (Windows Communication Foundation)?

A: LINQ to SQL supports serialization as XML via WCF by generating WCF serialization attributes and special serialization specific logic during code-generation.  You can turn on this feature in the designer by setting serialization mode to ‘Unidirectional’.  Note this is not a general solution for serialization as unidirectional mode may be insufficient for many use cases.

 

Q: How do I move entities between tiers in my multi-tier application?

A:  While it is possible to use WCF serialization to move entities between tiers it may be insufficient for your application as it will not allow for round-tripping of changes.  Defining a custom data exchange contract as part of your web service API is a better all around solution.

 

Q: Should I create a new DataContext in every business logic method?

A: The DataContext conforms to the Unit of Work design pattern.  Unless you are moving data between physical tiers between each operation you should keep your DataContext alive for the duration of work.

 

Q: Should I keep my DataContext in a static/global/shared variable?

A: The DataContext is not thread safe and is not meant to be shared.  A DataContext is meant to be used for a single unit or work or at most  for multiple consecutive units of work.

 

Q: Where should I put my business logic?  The system I’m currently developing uses static methods on the entities themselves for loading, saving and other operations.

A: The DataContext conforms to the Unit of Work design pattern.  A work context must exist and be maintained separate from the entities themselves.  You should either place all your business logic as methods on the DataContext or devise a separate business context that encapsulates a DataContext instance.  You should not be using static methods.

 

Q: Are LINQ to SQL entities Business Entities or Data Transfer Objects?  How do I build a business layer on top of LINQ to SQL?

A: LINQ to SQL entities are both business entities and data transfer objects.  LINQ to SQL takes the place of your Data Access Layer and is the basis for your Business Layer.  You can add business logic directly to the DataContext or encapsulate the DataContext in your own business context.  The purpose for making a separate business context would be to restrict access to other DataContext methods.  If this is not an issue for you, putting all business logic methods on the DataContext is the best choice.

 

Q: How can I keep entities cached beyond the lifetime of a single DataContext?  I want to keep a collection of entities in a cache so that all subsequent requests can read from this cache instead of going back to the database each time.

A: It is possible to cache entities beyond the lifetime of a single DataContext.  However, it is dangerous to do this for entities with defer loaded properties as you are likely to get accesses back to the originating DataContext if these properties are ever navigated.  You are also likely to unintentionally retain all entities materialized via that same DataContext causing what may appear to be a memory leak.  To alleviate these problems you can either turn deferred loading off when first retrieving these entities or you can dispose the DataContext after the entities are fully loaded using an operation such as ToList or ToArray.

 

Q: How can I re-attach an entity to a new DataContext?  When I try to do this I get an exception thrown.

A: LINQ to SQL does not support re-attaching entities.  Entities are never actually detached from their originating DataContexts. The Attach methods are intended to be used with entity instances that are newly created after round-tripping data from another physical tier.  LINQ to SQL detects that an entity belongs to another DataContext if any deferred properties are still unloaded.  It is possible to trick the DataContext into accepting entities from another DataContext by either not having deferred properties, pre-loading all of them or turning deferred loading off on the originating DataContext.

 

Q: How can I use globally cached entities to initialize the association properties of a new entity instance or to change an association property in order make an update?  When I try this I get strange behaviors like inserts I did not intend or exceptions thrown during SubmitChanges.

A: LINQ to SQL does not support mixing and matching entities loaded from different DataContext instances together in the same object graph.  Trying to do so is generally a bad idea.  Most association properties are bi-directional, so assigning one to a property of another or adding one to a collection property changes state and references in both entities.  This means that globally cached entities are being modified potentially on multiple threads at the same time (when running as a service).  As a general rule of thumb, a single connected entity graph should only be associated to a single unit of work at a time.  Instead of using globally cached entities to assign association properties, use entities retrieved from the DataContext you are using to perform the insert or update, or assign values to the foreign key fields directly to avoid extra round-trips to the database server.

 

解决方案

Regarding this...

 

Q: Where should I put my business logic?  The system I’m currently developing uses static methods on the entities themselves for loading, saving and other operations.

A: The DataContext conforms to the Unit of Work design pattern.  A work context must exist and be maintained separate from the entities themselves.  You should either place all your business logic as methods on the DataContext or devise a separate business context that encapsulates a DataContext instance.  You should not be using static methods.

 

...can you please expand a bit on the following aspects...

 

(1) How exactly do you "place all your business logic as methods on the DataContext"?

 

For example, we frequently create partial classes for those registered in our Linq Context. Then, we implement Extensibility Methods, such as OnValidate, inside each entity.

 

First, our way seems perfectly reasonable and the right thing to do-- put the work near the object that needs to be validated because that validation logic is specific to that particular object. Why would the per-class OnValidate Extensibility Methods exist as stubs in the generated class if not to suggest that one can implement them in a custom fashion. (This is what Scott Gu shows in his Linq-To-Sql series, BTW.)

 

Second, if this were put "on the DataContext" (maybe you mean "in"), what does that implementation look like? Does it mean to create a partial class on the DataContext and then put the class-specific validation logic there?

 

Can you explain? Maybe I am reading you incorrectly?

 

(2). Regarding "You should not be using static methods", I take it you mean do not create code that "uses static methods on the entities themselves for loading, saving and other operations", as the question poses above. Why do you say that?

 

Why exactly is it bad to have a static method such as DeleteWithCustomCascade(long targetId) or IsExisting(long targetId) in a custom implementation of a partial class for a table registered in the Linq context? Those methods, especially non-action queries such as IsExisiting, seem harmless as static, seem to work fine in production for us, and are a a lot less messy at the call site. Can you please explain why?


这篇关于LINQ to SQL:常见问题解答(FAQ)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆