Fluent NHibernate 忽略 ClassMap 中的属性,使用 FluentMappings

Posted

技术标签:

【中文标题】Fluent NHibernate 忽略 ClassMap 中的属性,使用 FluentMappings【英文标题】:Fluent NHibernate ignore property inside the ClassMap, using FluentMappings 【发布时间】:2012-03-15 20:18:05 【问题描述】:

我在我的项目中使用 NHibernate 3.1 和 Fluent NHibernate 作为 ORM。我需要一个被 Fluent NHibernate 忽略的 POCO 的属性。起初,我的帖子可能看起来与this question 完全相同,但事实并非如此。

我的复杂性首先来自 POCO 是在与映射不同的程序集中定义的事实,并且我正在为我的 POCO 使用 fluent 映射。我还有一个额外的要求,不要在会话工厂配置发生的地方编写 ingore-property 代码(这发生在模块外部的集中位置),而是作为定义映射的模块的一部分。理想情况下,我相信正确的地方是具体的ClassMap 实现,因为它确切地知道如何向 ORM 描述 POCO。

但是,我之所以坚持这一点,主要是因为这是我对 NHibernate 及其流畅 API 的第一次影响。到现在我对它的能力和可扩展性印象都很好,希望有办法实现我的需求,将映射相关的代码封装在对应的模块中。

这是我的配置,来自一个集中的地方:

List<Assembly> assemblies = GetModules().Select(x => x.GetType().Assembly).ToList();

ISessionFactory nhibernateSessionFactory = Fluently
    .Configure()
    .Mappings(m => assemblies.ForEach(asm => m.FluentMappings.AddFromAssembly(asm)))
    .Database(
        MsSqlConfiguration.MsSql2005
            .ShowSql()
            .ConnectionString(DatabaseConfig.Instance.ConnectionString))
    .ExposeConfiguration(c => new SchemaUpdate(c).Execute(true, true))
    .BuildSessionFactory();

我使用继承自 ClassMap 的标准类映射:

public class User

    public virtual int ID  get; set; 
    public virtual String Username  get; set; 
    public virtual String Password  get; set; 
    public virtual DateTime DateCreated  get; set; 
    public virtual DateTime DateModified  get; set; 

    // Must ignore
    public string ComputedProperty   get  ...  


public class UserMap : ClassMap<User>

    public UserMap()
    
        Table("User");
        Id(x => x.ID).GeneratedBy.Identity();
        Map(m => m.Username).Not.Nullable().Length(255).UniqueKey("User_Username_Unique_Key");
        Map(m => m.Password).Not.Nullable().Length(255);
        Map(m => m.DateCreated).Not.Nullable();
        Map(m => m.DateModified).Not.Nullable();
    

【问题讨论】:

你的映射类是什么样的,你的配置是什么样的? 我通过添加一些代码重新审视了我的问题 另见:***.com/questions/5830649/… 另见:***.com/questions/5830649/… 【参考方案1】:

我知道这篇文章有点老了,但我还是发布了,因为我没有找到任何关于这个主题的最新帖子。 我想最简单的方法应该是为每个我们不想持久化到表中的属性添加一个属性。通过添加一个扩展来检查它是否具有例如。具有 [NoEntity] 属性。

/// <summary>
/// Tells a single Property to not be persisted to table.
/// </summary>
public class NoEntity : Attribute  


    /// <summary>
/// Extension to ignore attributes
/// </summary>
public static class FluentIgnore

    /// <summary>
    /// Ignore a single property.
    /// Property marked with this attributes will no be persisted to table.
    /// </summary>
    /// <param name="p">IPropertyIgnorer</param>
    /// <param name="propertyType">The type to ignore.</param>
    /// <returns>The property to ignore.</returns>
    public static IPropertyIgnorer SkipProperty(this IPropertyIgnorer p, Type propertyType)
    
        return p.IgnoreProperties(x => x.MemberInfo.GetCustomAttributes(propertyType, false).Length > 0);
    

在流畅的配置设置中:

            return Fluently.Configure()
            .Database(DatabaseConfig)
            .Mappings(m => m.AutoMappings.Add(AutoMap.Assembly(typeof(IDependency).Assembly)
            .OverrideAll(p => 
                p.SkipProperty(typeof(NoEntity)); 
            ).Where(IsEntity)))
            .ExposeConfiguration(ValidateSchema)
            .ExposeConfiguration(BuildSchema)
            .BuildConfiguration();

【讨论】:

有趣的方法!如果我不必从 ORM 相关的注释中清除我的实体(我在单独的程序集中有映射,所以我可以从其他程序集中重用我的实体类而不带来任何 orm 依赖项)。我将尝试通过我的映射类来实现上述效果。 这将忽略任何具有任何属性的属性。可能不是期望或预期的行为。【参考方案2】:

我认为ClassMap 是忽略此属性的最佳位置是对的。

例子:

.Override<Shelf>(map =>  
  
  map.IgnoreProperty(x => x.YourProperty);
);

文档:https://github.com/jagregory/fluent-nhibernate/wiki/Auto-mapping#ignoring-properties

就从另一个程序集获取映射而言,它应该像这样简单(取决于您当前的配置):

.Mappings(m =>
              
                  m.FluentMappings.AddFromAssemblyOf<ProvideClassFromYourOtherAssembly>();
              );

【讨论】:

好的,但是这样我需要知道每个类必须在集中初始化位置忽略一个属性,并明确配置它。这就是我要避免的。想象一下,如果我要重构一个模块,我也必须修改应用程序的 ORM 初始化。 在您的问题中,您说“我有额外的要求,不要在会话工厂配置中设置 ingoring 属性(这发生在一个集中的地方),而是作为定义映射的模块的一部分。”但现在你说这是我的答案的问题?也许我不明白你在问什么,抱歉。 对不起,我有一个错误的印象,认为覆盖发生在配置会话工厂的集中位置,我的错。覆盖器接口可以放在我定义映射的同一个程序集中。 -1。你在叫什么.Override.Mappings?此外,链接已失效。 我已经更新了死链接。这真的值得 -1 来获得公认的答案吗?我无法控制其他人的网站,链接死了。至于示例,请查看更新的文档链接以更好地了解它们的内容 - github.com/jagregory/fluent-nhibernate/wiki/…【参考方案3】:

贾斯汀不会。这就是这个扩展的事情。只是你想要的属性会被忽略。

public class Person : IEntity 
 public virtual string Name..
 public virtual string Lastname..

 [NoProperty]
 public virtual string FullName // Not created property
  get  return Name +  " " + Lastname;  
 


public class Group : IEntity 
 public virtual string FullName.. //Created property

【讨论】:

以上是关于Fluent NHibernate 忽略 ClassMap 中的属性,使用 FluentMappings的主要内容,如果未能解决你的问题,请参考以下文章

如何告诉 Fluent NHibernate 不要映射类属性

NHibernate 2 + Fluent Nhibernate 中等信任

NHibernate + Fluent NHibernate 异常

用 Fluent Nhibernate 定义 NHibernate 过滤器的语法?

Fluent NHibernate and Mysql,SQLite

Fluent NHibernate - NHibernate.QueryException:无法解析属性