2

i have a field that i want to map as it links to a column in the database but i don't want any external class to access this field directly from my code (its only used in private calculations).

is this possible to have a field that i can map but it private using fluent nhibernate??

leora
  • 188,729
  • 360
  • 878
  • 1,366
  • 1
    You could also set your field to have `protected` accessors then external classes can't see or set it and no need to twist your Fluent mapping. – ChrisAnnODell Mar 25 '11 at 14:01
  • @ChrisAnnODell - wouldn't it have to be internal? How will the mapping class see it if it's only protected? – Mike Cole Mar 25 '11 at 14:18
  • The mapping class only uses the properties to define the mapping and does not attempt to access them. [`Internal`](http://msdn.microsoft.com/en-us/library/7c5ka91b(v=vs.80).aspx) would limit the property to objects defined in the same assembly, but nHibernate will inherit from the mapped class to create proxy so [`protected`](http://msdn.microsoft.com/en-us/library/bcd5672a(v=vs.71).aspx) is what you need to allow it to set the values from your repository. – ChrisAnnODell Mar 25 '11 at 14:39

4 Answers4

8

Yes it is possible. You can use the Reveal.Member static methods to map a private or hidden property

Map(Reveal.Member<string>("privateProperty"))
Vadim
  • 17,897
  • 4
  • 38
  • 62
3

I think this is what you're looking for.

Fluent mapping private properties

There’s been a point of contention for some users of Fluent NHibernate since the beginning, and that’s the lack of a method of mapping private and protected properties on their domain entities.

The issue stems from our use of lambda expressions for static reflection of your entities, one of the appealing properties of Fluent NHibernate; by utilising expressions we’re able to protect your mappings from refactoring side-effects. However, lambda expressions can only reference properties that are public on an object, so that makes it difficult to use against protected or private properties.

None of the solutions we have are ideal, we’ll be the first to admit that; but considering Fluent NHibernate was never designed to support these situations, and the limitations C# imposes on us, we’ve got some pretty reasonable choices. Each option comes with its own compromises, so it’s important you pick the method that has the compromises you’re more willing to accept; I’ll outline the pros and cons of each approach.

Zardify
  • 23
  • 1
  • 6
SquidScareMe
  • 3,108
  • 2
  • 24
  • 37
  • so is everything on this article possible today or is this a proposal listing options to the community. Does it support it today or not?? – leora Mar 25 '11 at 12:50
  • It appears all the techniques on that page can be used today. What made you question whether you could implement those patterns today? – SquidScareMe Mar 25 '11 at 13:21
0

This an example from my project. My domain classes have only public properties. No setters. The object is created through the constructor and data is manipulated using methods.

Entity

public class User: Entity
{
    private string _openid;
    private string _email;
    private string _username;
    private int roleid;

    // needed for mapping
    protected User() { }

    // your normal constructor
    public User(string openid)
    {
        Validator.NotNull(string openid, "openid is required.");
        _openid = openid;
    }

    public string Email
    {
        get { return _email; }
    }

    public string Username
    {
        get { return _username; }
    }

    public string Openid
    {
        get { return _openid; }
    }

   // Here are some methods
   // ... 
}

Mapping Class

public class UserMap : ClassMap<User>
    {
        public UserMap()
        {
            Table("user");

            // Reveal private attributes and map them
            Id(Reveal.Member<User>("_id")).Column("id");
            Map(Reveal.Member<User>("_username")).Column("username");
            Map(Reveal.Member<User>("_openid")).Column("openid_claimed_identifier");
            Map(Reveal.Member<User>("_email")).Column("email");

            // You need to create this mapping if you want to query using linq, 
            //see UserRepository below
            Map(x => x.Id, "id").ReadOnly();
            Map(x => x.Email, "email").ReadOnly();
            Map(x => x.Username, "username").ReadOnly();
            Map(x => x.Openid, "openid_claimed_identifier").ReadOnly();
        }
    }

Repository

public class UserRepository : Repository<User>, IUserRepository
    {
        public UserRepository(ISession session)
           : base(session)
        {
        }

        public User find_user_by_openid(string openid_claimed)
        {
            return base.FindBy(x => x.Openid == openid_claimed);
        }

        public User find_user_by_id(int id)
        {
            return base.FindBy(x => x.Id == id);
        }        

    }

One important thing to remember: do not use underscores within attribute names. Such as:

   public class User: Entity
    {
        //...
        private int role_id;
    }

Fluent NHibernate does not like it when you use a particular attribute to map References.

Artur Kedzior
  • 3,994
  • 1
  • 36
  • 58
0

You can at least minimize the harm of exposing internal structure by leaving only getters public:

public virtual int Id { get; protected set; }
Vytenis Bivainis
  • 2,308
  • 21
  • 28