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
这是一个必须使用的类。谁需要更多细节。我可以免费帮助他。
实现可以像:
[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 ;
完整备忘单(设计时和运行时 XPO)

对于按键或条件搜索对象,请使用以下命令:

编辑:2021-05-24
对于那些询问与复合键关联的人。这真是一场噩梦。默认情况下,Xpo 不提供。相反,您可以在子类中使用 Session.GetObjectByKey() 并在父类中使用新的 XPCollection。但实际上它有点慢,用人工钥匙的原生方式。
一目了然:使用人工/单键列以获得更好的任何 ORM 兼容性。否则以后在数据库中将是一场噩梦。例如,如果您支持另一个或替换当前的 ORM。
这是与复合键关联的代码。(请注意,您需要像上图那样动态转换它。您可能需要创建自定义 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; }
}
上述模型的动态运行时版本:
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";
最后,重要!
在任何 Xpo 中运行时实现 Composite-Keys 案例真的非常非常困难。而是替换为单列键(身份或人工。GUID 等)