不是 Dapper.Rainbow
Dapper.Rainbow
这在当前形式下是不可能的,但我在 github 中的拉取请求使这成为可能。
我很惊讶没有人建议使用Dapper.Contrib
. 我知道我问过该功能是否在 Rainbow 中。但我没想到没人会注意到这句话(尤其是粗体字):
现在我正在寻找可以更轻松地进行插入和更新的东西,并找到了 Dapper.Rainbow。我检查了它,并能够使用它来获取和插入如上所述的对象。我的
问题是,当 Product 具有导航属性时,我无法在该字段上进行插入。
...并提出替代方案,即 Dapper 库中已有的解决方案。我想我的问题应该更清楚,并明确询问在 github 中的整个 Dapper 库中是否存在解决方案。因此,在图书馆进行更多挖掘之后,我发现我的问题得到了支持。
Dapper.Contrib 的路径
我的项目一切正常,Rainbow
直到我需要更多。我得到了一些包含很多字段的表。如果我只是将我的对象提供给 Rainbow,那么它将对所有字段进行更新,这并不是很好。但这并没有让我迅速跳下船回到新罕布什尔州。所以在我实现自己的之前change tracking
,我不想重新发明轮子,特别是如果有人已经做得很好,我搜索了一下,发现了这个 SO 线程。该线程证实了我Rainbow
不支持更改跟踪的知识,但还有另一只野兽支持,它被称为Dapper.Contrib
. 所以我开始尝试它。
于是我们又见面了
ProductCategory 类型的成员 Category 不能用作参数值
我遇到了与Rainbow
. Contrib
不支持导航属性!?我开始觉得我在浪费时间Dapper
,而我非常追求的它提供的性能只是一厢情愿。直到...
WriteAttribute,来拯救......
此类SqlMapperExtensions.cs
位于项目中包含的文件中Dapper.Contrib
。我没有找到关于这个类的任何文档,也没有任何评论可以让它很容易被找到并冲着我大喊大叫hey I'm the one you're looking for
。当我如上所述将 Rainbow 放在一边时,我偶然发现了这一点。
这个类的用法和我做的一样IgnorePropertyAttribute
,它是一个属性,你可以用它来装饰你的类的属性。您应该使用此属性来装饰您不希望包含在创建的属性中的任何sql
属性Dapper
。因此,在我的示例中,让我告诉 Dapper 排除Category
我需要执行此操作的字段:
public class Product {
public int Id {get;set;}
public string Name {get;set;}
[Write(false)] // tell Dapper to exclude this field from the sql
public ProductCategory Category {get;set;}
public int CategoryId {get;set;}
}
我快到了
请记住,我选择的原因Contrib
是因为change tracking
功能。这个 SO 线程,与我在上面给出的相同链接,指出要启动更改跟踪,您需要为您的类提供一个接口并将其与Contrib
. 所以对于我的示例类,我需要:
public interface IProduct {
int Id {get;set;}
string Name {get;set;}
ProductCategory Category {get;set;}
int Category {get;set;}
}
// and implement it on my Product class
public class Product : IProduct {
public int Id {get;set;}
public string Name {get;set;}
[Write(false)]
public ProductCategory Category {get;set;}
int Category {get;set;}
}
我以为就是这样,差不多!您可能会问如果我根本不关心它,为什么我需要Category
在我的界面中定义它。Dapper
事实上,这只会导致一个问题,一个我会解决的问题。
在我的特定场景中,有时我需要在Category
现场工作,同时保持Product
对象的更改跟踪。为了保持跟踪能力,get 调用应该提供如下接口类型:
var product = connection.Get<IProduct>(id);
如果我不在我的界面中定义它,我将无法通过该调用访问该字段。Category
但是如果我在我的界面中定义它,我会得到熟悉的错误
{type} 类型的成员 {member} 不能用作参数值。
真的又来了?请停下来。
判决
不用担心,因为这很容易通过装饰接口成员来解决,就像我们为类所做的那样。因此,使一切正常的最终配置应该是:
public interface IProduct {
// I will not discuss here what this attribute does
// as this is documented already in the github source.
// Just take note that this is needed,
// both here and in the implementing class.
[Key]
int Id {get;set;}
string Name {get;set;}
[Write(false)]
ProductCategory Category {get;set;}
int Category {get;set;}
}
// and implement it on my Product class
public class Product : IProduct {
[Key]
public int Id {get;set;}
public string Name {get;set;}
[Write(false)]
public ProductCategory Category {get;set;}
int Category {get;set;}
}
如果您更喜欢使用Contrib
具有此change tracking
功能的方法,则可以使用此方法。如果您想使用Rainbow
并且像我一样遇到导航属性问题,那么您可以使用我的 pull request。它的工作方式与它WriteAttribute
唯一的工作方式相同Rainbow
。
如果你不喜欢用属性装饰你的类,那么这两个扩展项目都不适合你。我知道还有另一个扩展项目可以让您进行某种流利类型的配置,但这不与Dapper
github 中的库一起使用(不作为核心部分包含) 。我的偏好是仅使用核心库,这引导我调查整个库,看看是否已经存在或者是否可以对其进行改进以满足我的需求。这就是我在这里所做和解释的,对于Rainbow
和Contrib
。
我希望这个贡献,我添加的非常简单的类,我展示的配置技巧,以及引导我这些的场景,将帮助未来希望使用 Dapper 的人,并且会有与我类似的设置。此外,这个答案将使开发人员更多地了解 Dapper 能做什么和不能做什么。这个很棒的工具Dapper
值得一个更好的 wiki,我希望这个答案/文章在 SO 中即使在很小的方面也能有所帮助。
**如果我在这里写的东西已经写在某个地方,我在等待答案的两周时间内没有发现,那么我很高兴有人能将我链接到它。现在已经两周了,调查我的问题的 29 人没有提出任何链接或解决方案,所以我认为我在这里分享的信息对 Dapper* 来说是新的:)
注意:我修改了我的问题标题,以便其他人可以看到他们问题的潜在解决方案。新标题是基于我获得的关于 Dapper 的新知识。