C# 如何使用多个主键表动态创建DevExpress XPO?
我在这个主题中尝试了一个例子 但它只适用于单个主键表。因此,我搜索了更多信息,发现: 但是有很大的不同,我认为这并不令人满意,因为它谈到了复合键(一个键有很多列) 因此,我只需要一个从SQL-Server表动态创建XPO的示例: 我的表模式如下 XPOCollectionSource然后以服务器模式绑定到网格…这就是我所需要的 我使用的代码C# 如何使用多个主键表动态创建DevExpress XPO?,c#,.net,devexpress,xpo,devexpress-gridcontrol,C#,.net,Devexpress,Xpo,Devexpress Gridcontrol,我在这个主题中尝试了一个例子 但它只适用于单个主键表。因此,我搜索了更多信息,发现: 但是有很大的不同,我认为这并不令人满意,因为它谈到了复合键(一个键有很多列) 因此,我只需要一个从SQL-Server表动态创建XPO的示例: 我的表模式如下 XPOCollectionSource然后以服务器模式绑定到网格…这就是我所需要的 我使用的代码 XPServerCollectionSource GetServerModeSourceForTable(IDbConnection connecti
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);
}
一瞥。如何对动态创建的XPO对象使用
XPServerCollectionSource
。有两个主键。我不知道这是否是您想要的,但我将使用XPInstantFeedbackSource
共享我的代码
您可以通过以下网址获得更多信息:
XPLiteObject
LogXPOModel
Window
main窗口
就像那样-我的桌子有两个键;而且,它不会产生任何问题。
这是一个必须使用的类。他们需要更多的细节。我可以免费帮助他
实现方式可以类似于:
[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或替换当前ORM
下面是与复合键关联的代码。(请注意,您需要像上面的图片一样动态转换它。您可能需要创建自定义XPMemberInfo并重写GetValue(),以返回Session.GetObjectByKey()并创建新的XPCollection。(要做的事情非常糟糕,Xpo有史以来最糟糕,也不支持。所以,从技术上讲,复合键是一种糟糕的方式,除非您需要创建一个表将其绑定到网格。例如:-SalesOrderDetail表,它没有更多的子表)
最后,很重要!
在运行时很难实现组合键
在任何Xpo中。替换为单列键(标识或
人工的,人工的等)
我将XPInstantFeedbackSource与SQLite3一起使用,表也有两个主键。没有问题。您要求DevXPress支持吗?我认为他们可以快速帮助您。如果您需要我的帮助,我可以共享我的代码,但我的方法与您不同。一个表上不可能有两个主键。
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;
}
...
}
[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
[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";