คุณจับคู่ enum เป็นค่า int กับ NHibernate ได้อย่างไร?


88

คำถามบอกว่าทั้งหมดจริงๆแล้วค่าเริ่มต้นคือการแมปเป็น a stringแต่ฉันต้องการให้แมปเป็นintไฟล์.

ฉันกำลังใช้PersistenceModelสำหรับการตั้งค่าการประชุมของฉันหากสิ่งนั้นสร้างความแตกต่าง ขอบคุณล่วงหน้า.

อัปเดต พบว่าการเข้าสู่โค้ดเวอร์ชันล่าสุดจากหีบสามารถแก้ไขปัญหาของฉันได้


5
หากคุณแก้ไขปัญหาด้วยตัวเองคุณควรตอบแล้วทำเครื่องหมายว่าเป็นคำตอบที่ถูกต้องเพื่อให้ผู้ค้นหาในอนาคตพบ
Jeff Martin

รบกวนโพสต์คำตอบได้ไหม
mxmissile

เสร็จแล้ว ขออภัยในความล่าช้า. ฉันไม่แน่ใจจริงๆว่าควรจะทำอย่างไรกับคำถามที่ไม่ใช่คำถามเพราะฉันต้องการไลบรารีเวอร์ชันล่าสุด
Garry Shutler

2
อาหารสำหรับบ็อตของ Google: ฉันได้รับ "การเข้าถึงคอลเลคชันการโหลดอย่างผิดกฎหมาย" ก่อนที่จะใช้สิ่งนี้สำหรับการทำแผนที่ enum ของฉัน
4imble

คำตอบ:


84

วิธีกำหนดอนุสัญญานี้เปลี่ยนไปบางครั้งที่ผ่านมาตอนนี้:

public class EnumConvention : IUserTypeConvention
{
    public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
    {
        criteria.Expect(x => x.Property.PropertyType.IsEnum);
    }

    public void Apply(IPropertyInstance target)
    {
        target.CustomType(target.Property.PropertyType);
    }
}

4
นี่คือคำตอบที่ถูกต้องสำหรับเวอร์ชันล่าสุดของ fluent nhibernate
Sean Chambers

1
ดูเหมือนว่าจะใช้ได้ดีกับ enum ทุกประเภท แต่ถ้าคุณต้องการบางส่วนเป็นสตริงและบางส่วนเป็น ints ล่ะ? ฉันคิดว่าสิ่งนี้ควรกำหนดค่าได้ที่ระดับการแมปคุณสมบัติ
UpTheCreek

4
ดูคำตอบโดย @SztupY ด้านล่างที่ขยายสิ่งนี้เพื่ออนุญาตให้มีค่าว่างเปล่า stackoverflow.com/questions/439003/…
จอนอดัมส์

45

ดังที่ได้กล่าวไปแล้วการได้ Fluent NHibernate เวอร์ชันล่าสุดออกจากลำตัวทำให้ฉันไปถึงที่ที่ฉันต้องการ ตัวอย่างการแมป enum ด้วยรหัสล่าสุดคือ:

Map(quote => quote.Status).CustomTypeIs(typeof(QuoteStatus));

ประเภทที่กำหนดเองบังคับให้จัดการเป็นอินสแตนซ์ของ enum แทนที่จะใช้GenericEnumMapper<TEnum>.

ฉันกำลังพิจารณาที่จะส่งแพตช์เพื่อให้สามารถเปลี่ยนระหว่าง enum mapper ที่ยังคงมีสตริงและอันที่ยังคงมี int อยู่เนื่องจากดูเหมือนว่าคุณควรจะตั้งค่าเป็นแบบแผนได้


สิ่งนี้เกิดขึ้นจากกิจกรรมล่าสุดของฉันและสิ่งต่างๆได้เปลี่ยนแปลงไปใน Fluent NHibernate เวอร์ชันใหม่กว่าเพื่อให้ง่ายขึ้น

ในการทำให้ enums ทั้งหมดถูกแมปเป็นจำนวนเต็มคุณสามารถสร้างการประชุมได้ดังนี้:

public class EnumConvention : IUserTypeConvention
{
    public bool Accept(IProperty target)
    {
        return target.PropertyType.IsEnum;
    }

    public void Apply(IProperty target)
    {
        target.CustomTypeIs(target.PropertyType);
    }

    public bool Accept(Type type)
    {
        return type.IsEnum;
    }
}

จากนั้นการทำแผนที่ของคุณจะต้องเป็น:

Map(quote => quote.Status);

คุณเพิ่มการประชุมในการทำแผนที่ Fluent NHibernate ของคุณเช่นนั้น

Fluently.Configure(nHibConfig)
    .Mappings(mappingConfiguration =>
    {
        mappingConfiguration.FluentMappings
            .ConventionDiscovery.AddFromAssemblyOf<EnumConvention>();
    })
    ./* other configuration */

3
โดยมี "โหมด int" เป็นค่าเริ่มต้น ใครยังคง enums เป็นสตริง!
Andrew Bullock

4
อาจเป็นฐานข้อมูลเดิมที่มีค่าสตริงอยู่แล้ว
Chris Haines

4
+1 hainesy. @ Andrew Bullock: ตอบคำถามของคุณ: ใครก็ตามที่เกี่ยวข้องกับฐานข้อมูลจริง
Sky Sanders

มีอินเทอร์เฟซ IProperty ใน FN หรือไม่?
Tien Do

40

อย่าลืมเกี่ยวกับ enums ที่เป็นโมฆะ (เช่นExampleEnum? ExampleProperty)! ต้องตรวจสอบแยกกัน นี่คือวิธีดำเนินการกับการกำหนดค่าสไตล์ FNH ใหม่:

public class EnumConvention : IUserTypeConvention
{
    public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
    {
        criteria.Expect(x => x.Property.PropertyType.IsEnum ||
            (x.Property.PropertyType.IsGenericType && 
             x.Property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>) &&
             x.Property.PropertyType.GetGenericArguments()[0].IsEnum)
            );
    }

    public void Apply(IPropertyInstance target)
    {
        target.CustomType(target.Property.PropertyType);
    }
}

4
+1 สำหรับการเพิ่มนี้! เวอร์ชันแรกใช้ไม่ได้กับ enums ที่เป็นโมฆะ (ยังคงเป็นสตริง)
longda

@SztupY ประเภทคอลัมน์ในฐานข้อมูลคือint? และเมื่อประเภทยอมรับ Flags? ชอบ:MyEnum.Active | MyEnum.Paused
ridermansb

@RidermandeSousaBarbosa: สำหรับธงตรวจสอบที่นี่: stackoverflow.com/questions/2805661/…
SztupY

25

นี่คือวิธีที่ฉันได้แมปคุณสมบัติ enum ด้วยค่า int:

Map(x => x.Status).CustomType(typeof(Int32));

เหมาะกับฉัน!


2
ขอขอบคุณที่ให้คำตอบที่ง่ายที่สุด
Mike

คุณสมบัติเดียวของฉันคือคุณต้องจำไว้ว่าต้องใช้กับทุก enum นั่นคือสิ่งที่สร้างขึ้นเพื่อการประชุม
Garry Shutler

สิ่งนี้ใช้ได้กับการอ่าน แต่ล้มเหลวเมื่อฉันลองใช้แบบสอบถามเกณฑ์ การตั้งค่าการประชุม (ดูคำตอบสำหรับคำถามนี้) ได้ผลในทุกกรณีที่ฉันพยายาม
Thomas Bratt

ฉันคิดว่ามันเยี่ยมมาก - แต่สิ่งนี้จะทำให้เกิดปัญหา: ดูโพสต์นี้ nhforge.org/blogs/nhibernate/archive/2008/10/20/…
UpTheCreek

@UpTheCreek ดูเหมือนว่าสิ่งนี้ได้รับการแก้ไขแล้วและได้รับการแนะนำโดย James Gregory จากทีม NH: mail-archive.com/fluent-nhibernate@googlegroups.com/…
Ilya Kogan

1

สำหรับผู้ที่ใช้ Fluent NHibernate กับ Automapping (และอาจเป็นคอนเทนเนอร์ IoC):

IUserTypeConventionเป็น @ มั๊ยคำตอบ 's ด้านบน: https://stackoverflow.com/a/1706462/878612

public class EnumConvention : IUserTypeConvention
{
    public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
    {
        criteria.Expect(x => x.Property.PropertyType.IsEnum);
    }

    public void Apply(IPropertyInstance target)
    {
        target.CustomType(target.Property.PropertyType);
    }
}

การกำหนดค่า Fluent NHibernate Automapping สามารถกำหนดค่าได้ดังนี้:

    protected virtual ISessionFactory CreateSessionFactory()
    {
        return Fluently.Configure()
            .Database(SetupDatabase)
            .Mappings(mappingConfiguration =>
                {
                    mappingConfiguration.AutoMappings
                        .Add(CreateAutomappings);
                }
            ).BuildSessionFactory();
    }

    protected virtual IPersistenceConfigurer SetupDatabase()
    {
        return MsSqlConfiguration.MsSql2008.UseOuterJoin()
        .ConnectionString(x => 
             x.FromConnectionStringWithKey("AppDatabase")) // In Web.config
        .ShowSql();
    }

    protected static AutoPersistenceModel CreateAutomappings()
    {
        return AutoMap.AssemblyOf<ClassInAnAssemblyToBeMapped>(
            new EntityAutomapConfiguration())
            .Conventions.Setup(c =>
                {
                    // Other IUserTypeConvention classes here
                    c.Add<EnumConvention>();
                });
    }

* จากนั้นCreateSessionFactoryสามารถใช้ใน IoC เช่น Castle Windsor (โดยใช้ PersistenceFacility และตัวติดตั้ง) ได้อย่างง่ายดาย *

    Kernel.Register(
        Component.For<ISessionFactory>()
            .UsingFactoryMethod(() => CreateSessionFactory()),
            Component.For<ISession>()
            .UsingFactoryMethod(k => k.Resolve<ISessionFactory>().OpenSession())
            .LifestylePerWebRequest() 
    );


0

คุณควรเก็บค่าเป็น int / tinyint ในตาราง DB ของคุณ สำหรับการแมป enum ของคุณคุณต้องระบุการแมปให้ถูกต้อง โปรดดูการทำแผนที่และตัวอย่าง enum ด้านล่าง

คลาสการทำแผนที่

คลาสสาธารณะ TransactionMap: ClassMap Transaction
{
    TransactionMap สาธารณะ ()
    {
        // การแมปอื่น ๆ
        .....
        // การแมปสำหรับ enum
        แผนที่ (x => x.Status, "สถานะ"). CustomType ();

        ตาราง ("ธุรกรรม");
    }
}

Enum

Public enum TransactionStatus
{
   กำลังรอ = 1,
   ประมวลผล = 2,
   RolledBack = 3,
   ถูกบล็อก = 4,
   คืนเงิน = 5,
   แล้วประมวลผล = 6,
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.