在类之间有双向映射是很常见的,尤其是在带有 ORM 的应用程序中。像这样:
public class Product
{
private List<Price> HistoricPrices { get; private set;}
}
public class Price
{
private Product Product { get; set; }
}
是否有一种公认的方法可以在代码中维护这种关系?这样一来,当我为产品添加价格时,Product 属性会自动设置吗?
理想情况下,我正在寻找一种易于重用的解决方案。必须向集合中添加一些东西然后手动设置相反的关系似乎是错误的。
请注意,这不是关于如何为产品和价格建模的问题,而是关于如何为双向关系建模的问题。在很多情况下,这是完全合理的。
最佳答案
首先,我认为您提供的示例令人困惑 - 像价格这样的东西被建模为对象或引用具有价格的实体并不常见。但我认为这个问题是合理的——在 ORM 世界中,这有时被称为图形一致性。据我所知,没有一个明确的方法来解决这个问题,有几种方法。
让我们从稍微改变示例开始:
public class Product
{
private Manufacturer Manufacturer { get; private set; }
}
public class Manufacturer
{
private List<Product> Products { get; set; }
}
所以每个产品都有一个制造商,每个制造商都可以有一个产品列表。该模型的挑战在于,如果 Product 类和 Manufacturer 类保持相互断开连接的引用,则更新一个会使另一个无效。
有几种方法可以解决这个问题:
消除循环引用。这解决了问题,但降低了对象模型的表现力且更难使用。
更改代码,使产品中的制造商引用和制造商中的产品列表自反。换句话说,改变一个会影响另一个。这通常需要 setter 和集合的一些代码来拦截更改并将它们反射(reflect)到彼此。
根据另一个属性管理一个属性。因此,不是在 Product 中存储对制造商的引用,而是通过搜索所有制造商来计算它,直到找到拥有您的制造商。相反,您可以在 Product 类中保留对 Manufacturer 的引用并动态构建 Products 列表。在这种方法中,您通常会将关系的一侧设置为只读。顺便说一下,这是标准的关系数据库方法 - 实体通过在一个地方管理的外键相互引用。
从两个 类中将关系外部化,并在单独的对象(在 ORM 中通常称为数据上下文)中对其进行管理。当 Product 想要返回其制造商时,它会询问 DataContext。当制造商想要返回产品列表时,它也会这样做。在内部,有很多方法可以实现数据上下文,一组双向字典并不少见。
最后,我要提一下,您应该考虑使用可以帮助您管理图形一致性的 ORM 工具(如 NHibernate 或 CSLA)。这通常不是一个容易正确解决的问题 - 一旦您开始探索多对多关系、一对一关系和对象的延迟加载等情况,它很容易变得非常复杂。您最好使用现有的库或产品,而不是发明自己的机制。
这里有一些 links那谈bidirectional associations在 NHibernate 中,您可能会发现它很有用。
这是一个代码示例,您可以使用方法 #2 自己直接管理关系 - 这通常是最简单的。请注意,只有关系的一侧是可编辑的(在本例中为制造商)- 外部消费者无法直接设置产品的制造商。
public class Product
{
private Manufacturer m_manufacturer;
internal Manufacturer Manufacturer
{
get { return m_manufacturer; }
set { m_manufacturer = value; }
}
}
public class Manufacturer
{
private List<Product> m_Products = new List<Product>();
public IEnumerable<Product> Products { get { return m_Products.AsReadOnly(); } }
public void AddProduct( Product p )
{
if( !m_Products.Contains( p ) )
{
m_Products.Add( p );
p.Manufacturer = this;
}
}
public void RemoveProduct( Product p )
{
m_Products.Remove( p );
p.Manufacturer = null;
}
}
关于c# - 维护类之间的双向关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/950776/
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此
在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee
我正在检查一个Rails项目。在ERubyHTML模板页面上,我看到了这样几行:我不明白为什么不这样写:在这种情况下,||=和ifnil?有什么区别? 最佳答案 在这种特殊情况下没有区别,但可能是出于习惯。每当我看到nil?被使用时,它几乎总是使用不当。在Ruby中,很少有东西在逻辑上是假的,只有文字false和nil是。这意味着像if(!x.nil?)这样的代码几乎总是更好地表示为if(x)除非期望x可能是文字false。我会将其切换为||=false,因为它具有相同的结果,但这在很大程度上取决于偏好。唯一的缺点是赋值会在每次运行
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
我的问题的一个例子是体育游戏。一场体育比赛有两支球队,一支主队和一支客队。我的事件记录模型如下:classTeam"Team"has_one:away_team,:class_name=>"Team"end我希望能够通过游戏访问一个团队,例如:Game.find(1).home_team但我收到一个单元化常量错误:Game::team。谁能告诉我我做错了什么?谢谢, 最佳答案 如果Gamehas_one:team那么Rails假设您的teams表有一个game_id列。不过,您想要的是games表有一个team_id列,在这种情况下
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
📢博客主页:https://blog.csdn.net/weixin_43197380📢欢迎点赞👍收藏⭐留言📝如有错误敬请指正!📢本文由Loewen丶原创,首发于CSDN,转载注明出处🙉📢现在的付出,都会是一种沉淀,只为让你成为更好的人✨文章预览:一.分辨率(Resolution)1、工业相机的分辨率是如何定义的?2、工业相机的分辨率是如何选择的?二.精度(Accuracy)1、像素精度(PixelAccuracy)2、定位精度和重复定位精度(RepeatPrecision)三.公差(Tolerance)四.课后作业(Post-ClassExercises)视觉行业的初学者,甚至是做了1~2年
由于匿名block和散列block看起来大致相同。我正在玩它。我做了一些严肃的观察,如下所示:{}.class#=>Hash好的,这很酷。空block被视为Hash。print{}.class#=>NilClassputs{}.class#=>NilClass为什么上面的代码和NilClass一样,下面的代码又显示了Hash?puts({}.class)#Hash#=>nilprint({}.class)#Hash=>nil谁能帮我理解上面发生了什么?我完全不同意@Lindydancer的观点你如何解释下面几行:print{}.class#NilClassprint[].class#A