如何映射通过只读属性访问的集合? [英] How do I map a collection accessed through a read only property?

查看:141
本文介绍了如何映射通过只读属性访问的集合?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何使用约定来映射零件集合?

  public class Part 
{
public virtual int Id {get;组; }
public virtual string Name {get;组; }
}

public class Car
{
private readonly List< Part> _parts = new List< Part>();

public virtual int Id {get;组; }

公共虚拟IList< Part>零件
{
得到{return _parts.AsReadOnly(); }
}
}

我已经尝试了这个约定,但总是期望没有下划线前缀的字段名称:

$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ {
public void Apply(IOneToManyCollectionInstance实例)
{
instance.Access.ReadOnlyPropertyThroughCamelCaseField(CamelCasePrefix.Underscore);


$ / code $ / pre

我已经用1.2.0.694 2.0.0.698生成相同的结果:
$ b $ pre $ code>类'TestFluentNHibernate.Car'$中找不到字段' b $ b


解决方案

首先,您的_parts成员无法阅读-只要。 NHibernate需要写访问权限来设置值/引用。要通过Parts属性返回一个真正的只读集合,你必须返回一个System.Collections.ObjectModel.ReadOnlyCollection。如果你只是返回f.ex,这也删除在读/写集合类型中找到的所有方法。 list.AsReadOnly()。以这种方式返回的只读列表仍然具有.Add()方法和其他编辑集合的方法,但是它们会导致运行时异常,因此返回ReadOnlyCollection开头是防止这种情况的一个很好的选择。



很多人似乎都喜欢返回一个IEnumerable,它也是只读的,但是它可以转换为一个List或者其他的读/写集合类型并且被改变。



您必须实现AddPart和RemovePart方法,以允许外部代码将项目添加到只读集合中。

您的约定看起来是正确的,我使用1.2.0.694完全相同的语法,我的约定:

  instance.Key.Column(instance.EntityType.Name +Fk); 
instance.Fetch.Subselect();
instance.Inverse();
instance.Cascade.All();
instance.Access.ReadOnlyPropertyThroughCamelCaseField(CamelCasePrefix.Underscore);

示例类:

  public class Car 
{
private List< Part> _部分;
$ b $ public Car()
{
//初始化成员集合_parts
_parts = new List< Part>();
}

public virtual int Id {get;组; }

//在此返回readonlycollection,ReadOnlyCollection实现
// IList< T> ;, ICollection< T>,IEnumerable< T> ;, IList,ICollection,IEnumerable,
//所以返回的列表可以是从这些基类继承的任何集合类型。
public ReadOnlyCollection< Part>零件
{
get {return new List< Part>(_ parts).AsReadOnly(); }}

$ b $ public AddPart(Part part)
{
//通常我不想重复
if(!_parts.Contains部分))
_parts.Add(part);
}
}


How do I map the collection of Parts using a convention?

public class Part
{
  public virtual int Id { get; set; }
  public virtual string Name { get; set; }
}

public class Car
{
  private readonly List<Part> _parts = new List<Part>();

  public virtual int Id { get; set; }

  public virtual IList<Part> Parts
  {
    get { return _parts.AsReadOnly(); }
  }
}

I have tried this convention but it always expects the field name without an underscore prefix:

public class HasManyConvention : IHasManyConvention
{
  public void Apply(IOneToManyCollectionInstance instance)
  {
    instance.Access.ReadOnlyPropertyThroughCamelCaseField(CamelCasePrefix.Underscore);
  }
}

I've tried it with the 1.2.0.694 and 2.0.0.698 builds with the same result:

"Could not find field 'parts' in class 'TestFluentNHibernate.Car'"

解决方案

First of all, your _parts member can't be read-only. NHibernate needs write access to the member to set the value/reference. To return a truly read-only collection through the Parts property you have to return a System.Collections.ObjectModel.ReadOnlyCollection. This also "removes" all the methods found in the read/write collection types that are still there if you just return f.ex. list.AsReadOnly(). A read-only list returned in this way still have .Add() method and others to edit the collection, but they will cause a runtime exception so returning a ReadOnlyCollection to begin with is a great for preventing this possibility.

A lot of people seem to like returning an IEnumerable which is also read-only, but it can be cast to a List or other read/write collection type and changed that way.

You have to implement AddPart and RemovePart methods to allow external code to add and remove items to the read-only collection.

Your convention looks correct, I'm using the exact same syntax with 1.2.0.694 successfully, my convention:

     instance.Key.Column(instance.EntityType.Name + "Fk");
     instance.Fetch.Subselect();
     instance.Inverse();
     instance.Cascade.All();
     instance.Access.ReadOnlyPropertyThroughCamelCaseField(CamelCasePrefix.Underscore);

Example class:

public class Car
{
    private List<Part> _parts;

    public Car()
    {
        // Initialize member collection _parts
        _parts = new List<Part>();
    }

    public virtual int Id { get; set; }

    // Return readonlycollection here, ReadOnlyCollection implements 
    // IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable,
    // so the returned list can be any collection type inheriting from these base types.
    public ReadOnlyCollection<Part> Parts
    {
        get { return new List<Part>(_parts).AsReadOnly(); } }
    }

    public AddPart(Part part)
    {
        // Usually I don't want duplicates
        if (!_parts.Contains(part))
            _parts.Add(part);
    }
}

这篇关于如何映射通过只读属性访问的集合?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆