gpt4 book ai didi

orm - 如何使用 Dapper.Rainbow(或可选地使用 Dapper.Contrib)对具有导航属性的对象进行插入和更新

转载 作者:行者123 更新时间:2023-12-03 23:24:40 27 4
gpt4 key购买 nike

我最近才开始研究 Dapper。我正在测试它并且能够执行基本的 CRUD,我所说的基本的意思是在具有这种结构的类上工作:

public class Product {
public int Id {get;set;}
public string Name {get;set;}
}

现在我正在寻找可以更轻松地进行插入和更新的东西,并找到了 Dapper.Rainbow。我检查了它并能够使用它来获取和插入如上所述的对象。我的问题是当 Product有一个导航属性,我无法在该字段上插入。所以如果我有这个:
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

如果我更换 Category 可以解决这个问题带类型 int (数据库中相同的数据类型)。但是,如果我这样做,我将无法查询产品的类别信息,而不仅仅是(类别)ID。

因此,如果不求助于原始 Dapper,我如何使用具有导航属性的类进行插入和更新?我希望我可以执行以下操作并告诉 Dapper.Rainbow 忽略 Category插入或更新时。
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 中是可能的,我可以有一个代理对象 Category并将其分配给 Product并保存它,映射完美地工作。但我很想使用 Dapper,这就是为什么我正在探索并想了解如何完成这样的事情。

最佳答案

不与 Dapper.Rainbow

这是不可能的 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 一切正常直到我需要更多。我得到了一些包含很多字段的表。如果我只是给 Rainbow 提供我的对象,那么它会更新所有字段,这并不好。但这并没有使我迅速跳出船返回NH。所以在我实现我自己的 change tracking 之前,而且我不想重新发明轮子,特别是如果有人已经做得很好,我用谷歌搜索了一下 found this SO thread .那个帖子证实了我的知识 Rainbow不支持更改跟踪 但还有另一种野兽会这样做,它被称为 Dapper.Contrib .所以我开始尝试它。

于是我们又见面了

The member Category of type ProductCategory cannot be used as a parameter value



我遇到了与 Rainbow 相同的问题. Contrib不支持导航属性!?我开始觉得我在浪费时间 Dapper ,以及它提供的性能,我非常追求,只是一厢情愿。直到...

WriteAttribute,来拯救...

这个类(class)住在 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功能。 This SO thread ,与我上面给出的链接相同,指出要启动更改跟踪,您需要为您的类(class)创建一个界面,并将其与 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 调用应该使用这样的接口(interface)类型:
var product = connection.Get<IProduct>(id);

和那个电话我会 不是 可以访问 Category字段,如果我不会在我的界面中定义它。但是如果我在我的界面中定义它,我就会得到熟悉的错误

The member {member} of type {type} cannot be used as a parameter value.



真的又来了吗?请停止这个。

判决

不用担心,这个问题很容易通过装饰接口(interface)成员来解决,就像我们为类所做的那样。因此,使一切正常工作的最终配置应该是:
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 合作并且和我一样遇到导航属性问题,那么您可以 play with my pull request .它的工作方式与 WriteAttribute 相同只是它适用于 Rainbow .

如果您不喜欢用属性装饰您的类,那么这两个扩展项目都不适合您。我知道还有另一个扩展项目可以让你做某种流畅类型的配置,但确实如此 不是 Dapper 一起使用(不作为核心部分包含在内) github 中的库。我的偏好是仅使用核心库,这促使我调查整个库,看看是否已经存在,或者是否可以对其进行改进以满足我的需求。这就是我在这里所做和解释的,对于 RainbowContrib .

我希望这个贡献,我添加的非常简单的类,我展示的配置技巧,以及引导我这些的场景,将帮助将来希望使用 Dapper 的人,并且会有与我类似的设置。此外,这个答案将教育开发人员更多地了解 Dapper 可以做什么和不能做什么。此 很棒的工具 Dapper deserves a better wiki我希望这里的这个答案/文章即使在很小的程度上也能有所帮助。

**如果我在这里写的东西已经写在某个地方,我在等待答案的两周时间里没有找到,那么我会很高兴有人把我链接到它。现在已经两周了,调查我问题的 29 个人没有提出任何链接或解决方案,所以我认为我在这里分享的信息对 Dapper 来说是新的* :)

注意:我修改了我的问题标题,以便其他人可以看到他们问题的潜在解决方案。新标题基于我获得的有关 Dapper 的新知识。

关于orm - 如何使用 Dapper.Rainbow(或可选地使用 Dapper.Contrib)对具有导航属性的对象进行插入和更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15708246/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com