public class Product { public int Id {get;set;} public string Name {get;set;} }
现在我正在寻找一些可以更容易地进行插入和更新并发现Dapper.Rainbow的东西.我检查了它,并能够使用它来获取和插入对象,如上所述.我的问题是,当产品具有导航属性时,我不能在该字段上插入.所以如果我有这个:
public class Product { public int Id {get;set;} public string Name {get;set;} public ProductCategory Category {get;set;} }
我将无法做到这一点:
// connection is a valid and opened connection var db = TestDatabase.Init(connection,300); var newId = db.Products.Insert(newProduct);
因为这个原因:
The member Category of type ProductCategory cannot be used as a parameter value
如果我用类型int(数据库中相同的数据类型)替换类别,则可以解决问题.但是,如果我这样做,我将无法使用其类别信息查询产品,而不仅仅是(category)Id.
所以没有诉诸原始的Dapper,我如何使用导航属性的类进行插入和更新?我希望我可以执行以下操作,并告诉Dapper.Rainbow在插入或更新时忽略类别.
public class Product { public int Id {get;set;} public string Name {get;set;} public ProductCategory Category {get;set;} public int CategoryId {get;set;} // this will be the same field name in the database }
这个场景是可以使用NHibernate,我可以有一个代理对象的类别并将其分配给产品并保存,并且映射工作完美.但是我很想使用Dapper,这就是为什么我正在探索,想要学习如何做这样的事情.
解决方法
这是不可能的Dapper.Rainbow在其当前的形式,但my pull request in github使这成为可能.
我很惊讶,没有人建议使用Dapper.Contrib.我知道我问Rainbow是否有功能.但是我没想到没有人会注意到这个声明(特别是粗体字):
Now I was looking for something that would make it easier to do
inserts and updates and found Dapper.Rainbow. I checked it out and was
able to use it to get and insert objects as described above. My
problem is that when Product has a navigation property I can’t do an
insert on that field.
…并提出一个替代方案,一个已经在Dapper库中的解决方案.我想我应该更清楚我的问题,并明确询问一个解决方案是否存在于整个Dapper library that is in github的某个地方.所以在更多的挖掘图书馆后,我发现有一个支持我的问题.
Dapper.Contrib的路径
所有这些都与我的项目和彩虹工作良好,直到我需要更多的工作.我有一些表中有很多字段.如果我只是给Rainbow我的对象,那么它将对所有的字段进行更新,这不是很好.但是,这并不意味着我很快就跳出船,回到NH.所以在我实现自己的变更跟踪之前,我不想重新发明,特别是如果有人已经做了一个很好的工作,我已经在7月2日上网了.这个线程证实了我的知识,Rainbow不支持更改跟踪,但是另一个野兽,它被称为Dapper.Contrib.所以我开始尝试了.
所以我们再见面
The member Category of type ProductCategory cannot be used as a
parameter value
我和彩虹有同样的问题. Contrib不支持导航属性!我开始感觉到我正在用Dapper浪费我的时间,而且我所追求的表现只会是一厢情愿.直到…
WriteAttribute来到救援…
该类生活在Dapper.Contrib项目中包含的sqlMapperExtensions.cs文件中.我没有找到关于这个课程的任何文件,也没有任何意见可以很容易找到,并且对我说话,并说嘿,我是你正在寻找的.当我按照上面所述放置彩虹时,我偶然发现.
这个类的用法和我用IgnorePropertyAttribute一样,它是一个属性,你可以用它来装饰你的类的属性.您应该使用此属性来装饰任何不需要包含在Dapper创建的sql中的属性.所以在我的例子中,我告诉Dapper排除我需要做的类别字段:
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的原因是因为更改跟踪功能. This SO thread,我上面提到的相同的链接指出,要进行更改跟踪,您需要为您的课程提供一个界面,并与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;} }
我以为是,几乎!你可能会问我为什么需要在我的界面中定义类别,如果Dapper根本不关心它.其实这只会造成一个问题,我会解决的问题.
在我的具体情况下,有时我需要在“类别”字段上工作,同时保留“产品”对象的更改跟踪.为了保持跟踪功能,应该使用如下所示的接口类型来提供get call:
var product = connection.Get<IProduct>(id);
并且通过该调用,如果我不在界面中定义它,我将无法访问类别字段.但是如果我在我的界面中定义它,那么我会得到一个熟悉的错误
The member {member} of type {type} cannot be used as a parameter
value.
真的呢请停止.
判决
不需要担心,通过装饰接口成员,就像我们为该类做的一样,这个容易解决.所以使一切工作的最终配置应该是:
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,则可以使用此方法.如果你想和Rainbow一起工作,并且像导航属性一样有问题,那么你可以在play with my pull request.它的工作方式与WriteAttribute一样,只能与Rainbow一起使用.
如果您不是使用属性装饰课程的粉丝,则扩展项目不适合您.我知道还有另一个扩展项目可以让你做某种流畅的配置,但这并不是与github中的Dapper库(不包括在内).我的偏好是与核心图书馆合作,导致我调查整个图书馆,看看是否已经存在,或者是否可以改进以满足我的需要.这就是我在这里所做的和解释,对于彩虹和Contrib.
我希望这个贡献,我添加的非常简单的类,我显示的配置提示,以及引导我的场景,将会帮助将来有人使用Dapper,并且将有类似的设置.此外,这个答案将教育开发者更多的是Dapper可以做什么和不能做的.这个伟大的工具叫做Dapper deserves a better wiki,我希望这里的这个答案/文章有助于甚至在一个小的方式.
**如果我在这里写的内容已经写在某个地方,那么我在两周的时间内没有发现我一直在等待一个答案,那么我会很乐意让任何人联系我.现在已经有两个星期了,29个人看了我的问题没有建议任何链接或解决方案,所以我认为我在这里分享的信息是新的Dapper *