简体   繁体   English

如何使用多个主键表动态创建 DevExpress XPO?

[英]How to create DevExpress XPO dynamically with multiple primary-keys table?

I try example in this topic https://github.com/DevExpress-Examples/XPO_how-to-create-an-xpclassinfo-descendant-to-dynamically-build-a-persistent-class-structure-e1729我在本主题中尝试示例https://github.com/DevExpress-Examples/XPO_how-to-create-an-xpclassinfo-descendant-to-dynamically-build-a-persistent-class-structure-e1729

But It only works for single primary key tables.但它仅适用于单个主键表。 So i searched more Found this: https://github.com/DevExpress-Examples/XPO_how-to-create-persistent-classes-mapped-to-tables-with-a-composite-primary-key-at-runtime-e4606所以我搜索了更多发现这个: https://github.com/DevExpress-Examples/XPO_how-to-create-persistent-classes-mapped-to-tables-with-a-composite-primary-key-at-runtime-e4606

Buts there's big different and I think its not satisfy because it speaking about composite key( one Key which have many columns) So all I need please an example of creating XPO dynamically from SQL -Server Table: My Table Schema as following但是有很大的不同,我认为它不令人满意,因为它谈到了复合键(一个有很多列的键)所以我需要一个从 SQL 动态创建 XPO 的示例 -Server Table: My Table Schema 如下

在此处输入图像描述

The XPOCollectionSource then binding to grid in server-mode… Thats all I need.然后 XPOCollectionSource 在服务器模式下绑定到网格……这就是我所需要的。

Code I Use我使用的代码

XPServerCollectionSource GetServerModeSourceForTable(IDbConnection connection, string tableName) {  
    XPDictionary dict = new ReflectionDictionary();  
    XPClassInfo classInfo = dict.CreateClass(dict.QueryClassInfo(typeof(LiteDataObject)),  
        tableName);  
    DBTable[] tables = ((ConnectionProviderSql)XpoDefault.GetConnectionProvider(connection,  
        AutoCreateOption.None)).GetStorageTables(tableName);  
    foreach (DBColumn col in tables[0].Columns) {  
        XPMemberInfo member = classInfo.CreateMember(col.Name, DBColumn.GetType(  
            col.ColumnType));  
        if (tables[0].PrimaryKey.Columns.Contains(col.Name))  
            member.AddAttribute(new KeyAttribute());  
    }  
    return new XPServerCollectionSource(new Session(XpoDefault.GetDataLayer(  
        connection, dict, AutoCreateOption.None)), classInfo);  
}  

At a glance.乍看上去。 How to use XPServerCollectionSource with Dynamically created XPO object.如何将XPServerCollectionSource与动态创建的 XPO object 一起使用。 with two primary keys.有两个主键。

https://github.com/DevExpress-Examples/XPO_how-to-create-persistent-classes-mapped-to-tables-with-a-composite-primary-key-at-runtime-e4606/blob/19.2.7%2B/CS/XpoConsoleApplication/XPComplexCustomMemberInfo.cs https://github.com/DevExpress-Examples/XPO_how-to-create-persistent-classes-mapped-to-tables-with-a-composite-primary-key-at-runtime-e4606/blob/19.2.7% 2B/CS/XpoConsoleApplication/XPComplexCustomMemberInfo.cs

This is a class must used.这是必须使用的 class。 who need more details about that.谁需要更多细节。 I can help him for free.我可以免费帮助他。

Implementation can be like:实现可以像:

[NonPersistent]
public class XPDynamicObject  : XPLiteObject
{
    public XPDynamicObject(Session session) : base(session) {}
    public XPDynamicObject(Session session, XPClassInfo classInfo) : base(session, classInfo) { }
}


       Button_Click or any event :

       XPDynamicObject.AutoSaveOnEndEdit = false;

        ReflectionDictionary dic = new ReflectionDictionary();
        var classInfo = dic.CreateClass(dic.GetClassInfo(typeof(XPDynamicObject)), "general.users");

        // WE MUST get schema from database .... via ConnectionProviderSql this is only way 
        var provider = XpoDefault.GetConnectionProvider(MSSqlConnectionProvider.GetConnectionString("(local)", "testdb"), AutoCreateOption.None) as ConnectionProviderSql;

        
        // Composite Key - this is only way to add composite key dynamically
        XPComplexCustomMemberInfo user_key = new 
        XPComplexCustomMemberInfo(classInfo, "user_key", typeof(object), new KeyAttribute(), new PersistentAttribute(), new BrowsableAttribute(false));
        user_key.AddSubMember("user_brn", typeof(int), new PersistentAttribute("user_brn"));
        user_key.AddSubMember("user_num", typeof(int), new PersistentAttribute("user_num"));

        var user_name = classInfo.CreateMember("user_name", typeof(string));
        user_name.AddAttribute(new PersistentAttribute("user_name"));
        

        dal = new SimpleDataLayer(dic, provider);

        XPServerCollectionSource xpServerCollectionSource = new XPServerCollectionSource(session, classInfo); // XPServerCollectionSource Only Editable server-mode datasource via ALlowNew, AllowEdit, AllowRemove properties

GridControl.DataSource = xpServerCollectionSource; GridControl.DataSource = xpServerCollectionSource;

Full Cheat Sheet (Design-Time and Run-Time XPOs)完整备忘单(设计时和运行时 XPO) 在此处输入图像描述

For Searching for Object by Key or Condition use following:要通过键或条件搜索 Object,请使用以下命令:

在此处输入图像描述

Edit: 2021-05-24编辑:2021-05-24

For those who asks about Associations with composite keys.对于那些询问与复合键关联的人。 Its really nightmare.这真是一场噩梦。 By default Xpo doesn't provide that.默认情况下,Xpo 不提供。 instead you can use a Session.GetObjectByKey() in child-class and a new XPCollection in parent class.相反,您可以在子类中使用 Session.GetObjectByKey() 并在父类 class 中使用新的 XPCollection。 But actually its something little slowly that native way with an artificial key.但实际上它有点慢,用人工钥匙的原生方式。

At a glance: Use Artifcial / Single Key Column for Better any ORM compatibility.一目了然:使用人工/单键列以获得更好的任何 ORM 兼容性。 Otherwise It will be nightmare in database later.否则以后在数据库中将是一场噩梦。 If you for example support another or replace current ORM.例如,如果您支持另一个或更换当前的 ORM。

Here's a code for associations with composite keys.这是与复合键关联的代码。 (Note that you need to convert it dynamically like above pictures. You maybe need to create custom XPMemberInfo and override GetValue() to return Session.GetObjectByKey() and create new XPCollection. (really bad stuff to do and worst ever and non-supported ever by Xpo. So Composite-Keys technically are bad way except if you need create Single Table bind it to grid. EX:- SalesOrderDetail table which doesn't have more child tables) (请注意,您需要像上图那样动态转换它。您可能需要创建自定义 XPMemberInfo 并覆盖 GetValue() 以返回 Session.GetObjectByKey() 并创建新的 XPCollection。(真的很糟糕,最糟糕的事情是不支持曾经由 Xpo。所以复合键在技术上是不好的方法,除非你需要创建单个表将其绑定到网格。例如:-没有更多子表的 SalesOrderDetail 表)

[Persistent("users")]
public class user : XPLiteObject
{
    public user(Session session) : base(session) { }
    public user(Session session, XPClassInfo classInfo) : base(session, classInfo) { }

    [Key, Persistent]
    public user_key user_key { get; set; }
    [Persistent("user_name")]
    public string user_name { get; set; }

    private XPCollection<Trans> _trans;
    public XPCollection<Trans> trans
    {
        get
        {
            if (_trans == null)
                _trans = new XPCollection<Trans>(Session, CriteriaOperator.Parse($"user_brn = {user_key.user_brn} AND user_num = {user_key.user_num}"));
            return _trans;
        }
    }

}

public class Trans : XPLiteObject
{
    public Trans(Session session) : base(session) { }
    public Trans(Session session, XPClassInfo classInfo) : base(session, classInfo) { }

    [Key,Persistent("TransID")]
    public int TransID { get; set; }

    public int user_brn { get; set; }
    public int user_num { get; set; }

    public user user
    {
        get
        {
            var key = new user_key();
            key.user_brn = 1;
            key.user_num = 3;
            var obj = Session.GetObjectByKey<user>(key, true);
            return obj;
        }
    }
}

// Composite-Key
public struct user_key
{
    [Persistent("user_brn")]
    public int user_brn { get; set; }
    [Persistent("user_num")]
    public int user_num { get; set; }
}

A Dynamic run-time version from above model: model 以上的动态运行时版本:

    class XPCompositeAssociationMemberInfo : XPCustomMemberInfo
    {
        public XPCompositeAssociationMemberInfo(XPClassInfo owner, string propertyName, Type propertyType, XPClassInfo referenceType, bool nonPersistent, bool nonPublic) : base(owner, propertyName, propertyType, referenceType, nonPersistent, nonPublic)
        {
        }

        public override object GetValue(object theObject)
        {
            XPDynamicObject val = theObject as XPDynamicObject;
            if(val != null)
            {
                var user_num = val.GetMemberValue("user_num");
                IdList vals = new IdList();
                vals.Add(1);
                vals.Add(user_num);
                return val.Session.GetObjectByKey(ReferenceType, vals);
            }
            return val;
        }
    }


  XPDynamicObject.AutoSaveOnEndEdit = false;

        ReflectionDictionary dic = new ReflectionDictionary();
        var userClassInfo = dic.CreateClass(dic.GetClassInfo(typeof(XPDynamicObject)), "users");

        // WE MUST get schema from database .... via ConnectionProviderSql this is only way 
        var provider = XpoDefault.GetConnectionProvider(MSSqlConnectionProvider.GetConnectionString("(local)", "testdb"), AutoCreateOption.None) as ConnectionProviderSql;
        //DBTable Table = provider.GetStorageTables("users")[0];
        
        // Composite Key - this is only way to add composite key dynamically
        XPComplexCustomMemberInfo user_key = new XPComplexCustomMemberInfo(userClassInfo, "user_key", typeof(object), new KeyAttribute(), new PersistentAttribute(), new BrowsableAttribute(false));
        user_key.AddSubMember("user_brn", typeof(int), new PersistentAttribute("user_brn"));
        user_key.AddSubMember("user_num", typeof(int), new PersistentAttribute("user_num"));
        
        var user_name = userClassInfo.CreateMember("user_name", typeof(string));
        user_name.AddAttribute(new PersistentAttribute("user_name"));

        var transClassInfo = dic.CreateClass(dic.GetClassInfo(typeof(XPDynamicObject)), "Trans");
        var TransID = transClassInfo.CreateMember("TransID", typeof(int), new KeyAttribute());
        var user_brn = transClassInfo.CreateMember("user_brn", typeof(int));
        var user_num = transClassInfo.CreateMember("user_num", typeof(int));
        XPCompositeAssociationMemberInfo userMI = new XPCompositeAssociationMemberInfo(transClassInfo, "user", typeof(object), userClassInfo, true, false);



        dal = new SimpleDataLayer(dic, provider);            
        Session session = new Session(dal);
        XPServerCollectionSource xpServerCollectionSource = new XPServerCollectionSource(session, transClassInfo); // XPServerCollectionSource Only Editable server-mode datasource via ALlowNew, AllowEdit, AllowRemove properties                        
        xpServerCollectionSource.DisplayableProperties = "TransID;user.user_key.user_num;user.user_name";

Finally, IMPORTANT !最后,重要!

Its really very very hard to achieve Composite-Keys cases at runtime in any Xpo.在任何 Xpo 中运行时实现 Composite-Keys 案例真的非常非常困难。 Instead replace with Single Column Key(Identity or Artificial one. GUID one etc.)而是替换为单列键(身份或人工。GUID 等)

I don't know if this is what you want, but I'll share my code using XPInstantFeedbackSource .我不知道这是否是您想要的,但我将使用XPInstantFeedbackSource分享我的代码。

You can get more information at How To Implement The Instant Feedback Mode Xpo您可以在如何实施即时反馈模式 Xpo中获得更多信息

XPLiteObject LogXPOModel XPLiteObject LogXPOModel

[Persistent("log.t_log")]
public class LogXPOModel : XPLiteObject
{
    [Key, DevExpress.Xpo.DisplayName("id")]
    public long id { get; set; }

    [Key, DevExpress.Xpo.DisplayName("recv_time")]    
    public long recv_time

    ...
}

Window MainWindow Window主窗口

public class MainWindow : Window
{
    public XPInstantFeedbackSource SqliteXPInstantFeedbackSource

    public MainWindow() {
        ...
        SqliteXPInstantFeedbackSource = new XPInstantFeedbackSource();
        SqliteXPInstantFeedbackSource.ObjectType = typeof(LogXPOModel);
        SqliteXPInstantFeedbackSource.ResolveSession += SqliteXPInstantFeedbackSource_ResolveSession;
        SqliteXPInstantFeedbackSource.DismissSession += SqliteXPInstantFeedbackSource_DismissSession;
        View.Grid.ItemsSource = SqliteXPInstantFeedbackSource;
    }
    
    ...
}

Like that — my table has two keys;就像那样——我的桌子有两个钥匙; and, it does not incur any problems.并且,它不会产生任何问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM