商信互联
在本课程中,您将学习如何将文件集合附加到业务对象。为此,将文件附件模块添加到应用程序中,并将实现新的Resume和PortfolioFileData业务类。该简历类将被用于存储和管理联系人的简历信息:文件中的数据收集和一个参考联系。该PortfolioFileData类将代表文件的数据收集项目。您还将学习如何在UI中显示和管理文件数据类型属性。
将文件附件模块添加到您的WinForms模块项目中。为此,请在“解决方案资源管理器”中显示的MySolution.Module.Win项目中找到WinModule.cs(WinModule.vb)文件。双击该文件以调用模块设计器。在“工具箱”中,展开DX。19.2:“ XAF模块”选项卡。将FileAttachmentsWindowsFormsModule项拖到设计器的“必需的模块”部分。
将文件附件模块添加到您的ASP.NET模块项目中。为此,请在解决方案资源管理器中显示的MySolution.Module.Web项目中找到WebModule.cs(WebModule.vb)文件。双击该文件以调用模块设计器。在“工具箱”中,展开DX。19.2:“ XAF模块”选项卡。将FileAttachmentsAspNetModule项目拖到设计器的“必需的模块”部分。
用以下代码替换自动生成的Resume类声明。
eXpress持久对象
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl;
using DevExpress.Xpo;
using MySolution.Module.BusinessObjects;
[DefaultClassOptions]
[ImageName("BO_Resume")]
public class Resume : BaseObject {
public Resume(Session session) : base(session) {}
private Contact contact;
public Contact Contact {
get {
return contact;
}
set {
SetPropertyValue(nameof(Contact), ref contact, value);
}
}
[Aggregated, Association("Resume-PortfolioFileData")]
public XPCollection<PortfolioFileData> Portfolio {
get { return GetCollection<PortfolioFileData>(nameof(Portfolio)); }
}
}
Imports DevExpress.Persistent.Base
Imports DevExpress.Persistent.BaseImpl
Imports DevExpress.Xpo
<DefaultClassOptions, ImageName("BO_Resume")> _
Public Class [Resume]
Inherits BaseObject
Public Sub New(ByVal session As Session)
MyBase.New(session)
End Sub
Private fContact As Contact
Public Property Contact() As Contact
Get
Return fContact
End Get
Set(ByVal value As Contact)
SetPropertyValue(NameOf(Contact), fContact, value)
End Set
End Property
<Aggregated(), Association("Resume-PortfolioFileData")> _
Public ReadOnly Property Portfolio() As XPCollection(Of PortfolioFileData)
Get
Return GetCollection(Of PortfolioFileData)(NameOf(Portfolio))
End Get
End Property
End Class
实体框架
using System;
using System.Linq;
using System.ComponentModel;
using System.Collections.Generic;
using DevExpress.Persistent.Base;
namespace MySolution.Module.BusinessObjects {
[DefaultClassOptions]
[ImageName("BO_Resume")]
public class Resume {
public Resume() {
Portfolio = new List<PortfolioFileData>();
}
[Browsable(false)]
public Int32 ID { get; protected set; }
public virtual IList<PortfolioFileData> Portfolio { get; set; }
public virtual Contact Contact { get; set; }
}
}
Imports System
Imports System.Linq
Imports System.ComponentModel
Imports System.Collections.Generic
Imports DevExpress.Persistent.Base
<DefaultClassOptions, ImageName("BO_Resume")> _
Public Class [Resume]
Public Sub New()
Portfolio = New List(Of PortfolioFileData)()
End Sub
<Browsable(false)> _
Public Property ID() As Int32
Public Overridable Property Portfolio() As IList(Of PortfolioFileData)
Public Overridable Property Contact() As Contact
End Class
public class MySolutionDbContext : DbContext {
//...
public DbSet<Resume> Resumes { get; set; }
}
Public Class MySolutionDbContext
Inherits DbContext
'...
Public Property Resumes() As DbSet(Of [Resume])
End Class
public class Contact : Person {
public Contact() {
//...
Resumes = new List<Resume>();
}
//...
public virtual IList<Resume> Resumes { get; set; }
}
Public Class Contact
Inherits Person
Public Sub New()
'...
Resumes = New List(Of [Resume])()
End Sub
'...
Public Overridable Property Resumes() As IList(Of [Resume])
End Class
声明PortfolioFileData类,这是FileAttachmentBase后代为XPO和FileAttachment的-为EF,和DocumentType枚举(为XPO)如下。
eXpress持久对象
public class PortfolioFileData : FileAttachmentBase {
public PortfolioFileData(Session session) : base(session) {}
protected Resume resume;
[Persistent, Association("Resume-PortfolioFileData")]
public Resume Resume {
get { return resume; }
set {
SetPropertyValue(nameof(Resume), ref resume, value);
}
}
public override void AfterConstruction() {
base.AfterConstruction();
documentType = DocumentType.Unknown;
}
private DocumentType documentType;
public DocumentType DocumentType {
get { return documentType; }
set { SetPropertyValue(nameof(DocumentType), ref documentType, value); }
}
}
public enum DocumentType { SourceCode = 1, Tests = 2, Documentation = 3,
Diagrams = 4, ScreenShots = 5, Unknown = 6 };
Public Class PortfolioFileData
Inherits FileAttachmentBase
Public Sub New(ByVal session As Session)
MyBase.New(session)
End Sub
Protected fResume As [Resume]
<Persistent(), Association("Resume-PortfolioFileData")> _
Public Property [Resume]() As [Resume]
Get
Return fResume
End Get
Set(ByVal value As [Resume])
SetPropertyValue(NameOf(Resume), fResume, Value)
End Set
End Property
Public Overrides Sub AfterConstruction()
MyBase.AfterConstruction()
fDocumentType = DocumentType.Unknown
End Sub
Private fDocumentType As DocumentType
Public Property DocumentType() As DocumentType
Get
Return fDocumentType
End Get
Set(ByVal value As DocumentType)
SetPropertyValue(NameOf(DocumentType), fDocumentType, value)
End Set
End Property
End Class
Public Enum DocumentType
SourceCode = 1
Tests = 2
Documentation = 3
Diagrams = 4
ScreenShots = 5
Unknown = 6
End Enum
实体框架
using System;
using System.Linq;
using System.ComponentModel;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl.EF;
namespace MySolution.Module.BusinessObjects {
[ImageName("BO_FileAttachment")]
public class PortfolioFileData : FileAttachment {
public PortfolioFileData()
: base() {
DocumentType = DocumentType.Unknown;
}
[Browsable(false)]
public Int32 DocumentType_Int { get; protected set; }
[System.ComponentModel.DataAnnotations.Required]
public Resume Resume { get; set; }
[NotMapped]
public DocumentType DocumentType {
get { return (DocumentType)DocumentType_Int; }
set { DocumentType_Int = (Int32)value; }
}
}
}
Imports Microsoft.VisualBasic
Imports System
Imports System.Linq
Imports System.ComponentModel
Imports System.Collections.Generic
Imports System.ComponentModel.DataAnnotations.Schema
Imports DevExpress.Persistent.Base
Imports DevExpress.Persistent.BaseImpl.EF
<ImageName("BO_FileAttachment")> _
Public Class PortfolioFileData
Inherits FileAttachment
Public Sub New()
MyBase.New()
DocumentType = DocumentType.Unknown
End Sub
<Browsable(false)> _
Public Property DocumentType_Int() As Int32
<System.ComponentModel.DataAnnotations.Required> _
Public Property [Resume]() As [Resume]
<NotMapped> _
Public Property DocumentType() As DocumentType
Get
Return CType(DocumentType_Int, DocumentType)
End Get
Set(ByVal value As DocumentType)
DocumentType_Int = CInt(Fix(value))
End Set
End Property
End Class
public class MySolutionDbContext : DbContext {
//...
public DbSet<PortfolioFileData> PortfolioFileData { get; set; }
public DbSet<FileAttachment> FileAttachments { get; set; }
}
Public Class MySolutionDbContext
Inherits DbContext
'...
Public Property PortfolioFileData() As DbSet(Of PortfolioFileData)
Public Property FileAttachments() As DbSet(Of FileAttachment)
End Class
在上面的代码中,您可以看到Resume和PortfolioFileData类与一对多关系相关。另一个重要的一点是,在XPO中,在AfterConstruction方法中初始化了PortfolioFileDataData.DocumentType属性,该方法在创建相应的对象之后被调用。
EF版本的代码包括一个明显的Entity Framework特性的变通办法。默认情况下,删除主对象不会导致引用对象的删除。唯一发生的是从引用对象到主对象的链接无效。仅当在删除时加载了引用的对象时,空化才会成功,但是如果从“列表视图”中删除了对象,则并非总是如此。为避免完整性冲突,应将类之间的关联配置为允许所引用的对象与主对象一起删除。在上面的代码中,这是通过“恢复”属性中的[System.ComponentModel.DataAnnotations.Required]属性完成的。PortfolioFileData类声明。
避免完整性违规的另一种方法是使用Fluent API调用Portfolio-Resume关系的WillCascadeOnDelete(true)方法。Fluent API请求应位于DbContext中。
请参阅在XPO文件附件属性和文件附件属性在实体框架主题以了解更多有关文件附件属性创建。
要指定File属性,请在“打开”对话框中附加一个文件,该文件通过“从文件添加...”()按钮调用。
要打开或保存附加到Portfolio集合的文件,或添加新文件,请使用集合随附的Open ...,另存为...或Add From File ...操作。
要将存储在当前FileData对象中的文件保存到指定的流,请使用IFileData.SaveToStream方法。
您可以在随XAF一起安装的Main Demo的Resume.cs(Resume.vb)文件中看到此处演示的代码。该MainDemo应用程序安装在%PUBLIC%\文件\ DevExpress的演示19.2 \组件\ eXpressApp框架\ MainDemo默认。可从http://demos.devexpress.com/XAF/MainDemo/在线获得ASP.NET版本。
下一课: 为最终用户提供几种视图变体