Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在运行时映射一对一关系_C#_Nhibernate_Linq To Nhibernate - Fatal编程技术网

C# 在运行时映射一对一关系

C# 在运行时映射一对一关系,c#,nhibernate,linq-to-nhibernate,C#,Nhibernate,Linq To Nhibernate,我正在尝试升级一个旧的CMS以使用NHibernate,并且不能太多地阻止原始数据库结构。这是导致问题的位。假设我有以下两个表: Articles: - Id (PK, Identity) - Title - Content Meta: - ArticleId (PK, FK to Articles) - Description - Keywords 我创建了以下类: public class Article { public virtual int Id { get; s

我正在尝试升级一个旧的CMS以使用NHibernate,并且不能太多地阻止原始数据库结构。这是导致问题的位。假设我有以下两个表:

Articles: 
- Id (PK, Identity)
- Title 
- Content 

Meta: 
- ArticleId (PK, FK to Articles)
- Description 
- Keywords 
我创建了以下类:

public class Article { 
  public virtual int Id { get; set; } 
  public virtual string Title { get; set; } 
  public virtual string Content { get; set; } 
} 

public class Meta : IComponent { 
  public virtual string Description { get; set; } 
  public virtual string Keywords { get; set; } 
}

public interface IComponent {
}
通常,Meta通常映射为Article类上的组件(或一对一关系)属性。但是,在我正在构建的应用程序中,管理员可以启用/禁用应用于文章的组件。我还希望他们能够扩展应用程序,在不接触Article类的情况下添加自己的组件

由于这些原因,我无法针对Article类添加属性。现在,在我的代码中,我希望能够说:

var articles = session.Query<Article>()
    .Fetch(a = a.Component<Meta>())
    .Where(a => a.Component<Meta>().Keywords.Contains("Some Word"))
    .ToList();

// This wouldn't generate an extra SQL statement
var keywords = articles[0].Component<Meta>().Keywords;
var articles=session.Query()
.Fetch(a=a.Component())
.Where(a=>a.Component().Keywords.Contains(“某个单词”))
.ToList();
//这不会生成额外的SQL语句
var关键字=文章[0]。组件()。关键字;
将生成以下SQL(或类似SQL):

选择*FROM Articles internal JOIN Articles.Id=Meta.ArticleId,其中Meta.Keywords,如“%Some Word%”

是否可以映射组件方法,以便它进行内部连接以获取元。这个概念看起来很简单,但我不知道从哪里开始。我非常感谢你的帮助


感谢您在NHibernate映射文件中指定提取类型。一对一xml的规范位于中。请注意,数字5有一个Join和Select选项,默认为Select。

鉴于此:

public class Article
{
    public virtual int ArticleId { get; set; }
    public virtual string Title { get; set; }
    public virtual string Content { get; set; }
}


public class Meta : IComponent
{
    public virtual Article Article { get; set; }

    public virtual int MetaId { get; set; }
    public virtual string Description { get; set; }
    public virtual string Keywords { get; set; }
}
好吧,您不能获取不属于实体的内容。因此,从您的示例来看,不可能从文章实体获取Meta

因此,如果您想获取文章的其他信息,只需将文章加入其中,然后在Linq中投影完整数据,例如:

var articles =
        from a in s.Query<Article>()
        join m in s.Query<Meta>() on a equals m.Article
        where m.Keywords.Contains("Some Word")
        select new { a, m };

foreach(var x in articles)
    Console.WriteLine("{0} {1}", x.a.Title, x.m.Description);
另一种方法,从Meta开始,然后获取文章;查询时,这将立即加入文章,即无延迟加载:

var artB =
        from m in s.Query<Meta>().Fetch(x => x.Article)
        where m.Keywords.Contains("Some Word")
        select m;

foreach (var x in artB)
    Console.WriteLine("{0} {1}", x.Article.Title, x.Description);
要保持一篇文章只有一个Meta,请在Meta的引用上放置一个唯一的:

create table Article
(
ArticleId int identity(1,1) not null primary key,
Title varchar(100) not null,
Content varchar(100) not null
);

create table Meta
(
    -- this prevents an Article having two Meta
ArticleId int not null references Article(ArticleId) unique, 

MetaId int identity(1,1) not null primary key,

Description varchar(100) not null,
Keywords varchar(100) not null
);

insert into Article(Title,Content) values('Great','Yeah')

insert into Meta(ArticleId, Description, Keywords) values(1,'Oh','Some Word');

以下解决方案是否有意义

您可以创建到组件的受保护映射,并通过此公共通用方法访问这些组件

通过这种方式,您可以选择立即/延迟加载组件

public class Article
{
    protected virtual ICollection<IComponent> Components { get; set; }

    public virtual T Component<T>() where T : IComponent
    {
        return Components.FirstOrDefault(c=>c.Type==typeof(T));
    }
}
公共类文章
{
受保护的虚拟ICollection组件{get;set;}
公共虚拟T组件(),其中T:IComponent
{
返回组件.FirstOrDefault(c=>c.Type==typeof(T));
}
}

这如何帮助我映射组件()?xml确定表之间映射的细节。组件只是对象中的一种类型。您需要在文章类中放入一个名为Compontent类型的Meta的属性,然后在配置XML中定义该属性和Meta(作为一对一)之间的关系。你能提供一个更详细的答案和一个例子请。请,这是什么意思“…管理员可以启用/禁用组件…”?嗨,谢谢你的回答。第二个选项为我提供了强大的键入功能,但是如果我有另一个组件,比如Meta2,那么它就会崩溃。我喜欢第一种方法中的想法(linq查询很简单,允许我向其他组件添加连接)。但是,它确实需要比理想情况下更多的工作,因为我必须为视图创建一个额外的模型,使其具有强类型。如果有一种方法可以说article.Component().Description(注意,可以相应地修改article类/映射),那就太好了。如果没有,那还是为你的帮助欢呼吧。好主意:-)虽然如果有人能在Linq到NH中实现这一点,这还不够:
Fetch(a=>a.Component())
因为投影需要一个别名(由编译器在设计时进行评估),所以为了挑剔,这将是API
Fetch(a=>new{art=a,meta=a.Component())
。试着给NHibernate的人发电子邮件,如果他们能接受这个想法。好的。为您的帮助干杯。我的猜测是,要么将其作为实体文章映射的一部分,要么将其作为一对多。查询中的问题是从article类开始,而显然应该从组件开始。通过这种方式,您可以使用联接同时加载组件和项目。正如Micheal提到的。这种方法适用于多个IComponent类型,除非你想一次查询多个组件,然后你需要加入,这是显而易见的。嗨,欢呼这看起来很有希望。不过,我不太确定如何映射组件。我的猜测是,我需要数据库中的一个表来说明哪些组件适用于本文。请让我知道你对此的想法。谢谢
create table Article
(
ArticleId int identity(1,1) not null primary key,
Title varchar(100) not null,
Content varchar(100) not null
);

create table Meta
(
    -- this prevents an Article having two Meta
ArticleId int not null references Article(ArticleId) unique, 

MetaId int identity(1,1) not null primary key,

Description varchar(100) not null,
Keywords varchar(100) not null
);

insert into Article(Title,Content) values('Great','Yeah')

insert into Meta(ArticleId, Description, Keywords) values(1,'Oh','Some Word');
public class Article
{
    protected virtual ICollection<IComponent> Components { get; set; }

    public virtual T Component<T>() where T : IComponent
    {
        return Components.FirstOrDefault(c=>c.Type==typeof(T));
    }
}