商信互联
本主题演示如何在DbContext上下文中使用业务模型创建简单的XAF应用程序。
本主题演示了可由解决方案向导自动生成的代码。如果要在现有XAF解决方案中实现演示的功能,请继续。如果要创建新的XAF解决方案,请改用向导。
DevExpress代码示例数据库(http://www.devexpress.com/example=E4375)中提供了完整的示例项目。
使用DevExpress v 19.2 XAF解决方案向导创建一个名为MySolution的新XAF解决方案。在“选择ORM”步骤中首先选择“实体框架代码”,然后单击“完成”。
在本主题中,我们将不详细描述实体和上下文实现,因为它已在MSDN中进行了描述(请参阅“新数据库的代码优先”)。在这里,我们假设您已经熟悉在代码中创建EF数据模型。
在模块项目中,实现以下Employee和Task类。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using DevExpress.Persistent.Base;
// ...
[DefaultClassOptions, ImageName("BO_Employee")]
public class Employee : INotifyPropertyChanged
{
private int id;
[Browsable(false)]
public int Id {
get { return id; }
protected set {
if (id != value) {
id = value;
OnPropertyChanged();
}
}
}
private string firstName;
public string FirstName {
get { return firstName; }
set {
if (firstName != value) {
firstName = value;
OnPropertyChanged();
}
}
}
private string lastName;
public string LastName {
get { return lastName; }
set {
if (lastName != value) {
lastName = value;
OnPropertyChanged();
}
}
}
private DateTime? birthday;
public DateTime? Birthday {
get { return birthday; }
set {
if (birthday != value) {
birthday = value;
OnPropertyChanged();
}
}
}
private List<Task> tasks;
public virtual List<Task> Tasks {
get { return tasks; }
set {
if (tasks != value) {
tasks = value;
OnPropertyChanged();
}
}
}
#region INotifyPropertyChanged members
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null) {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Runtime.CompilerServices
Imports DevExpress.Persistent.Base
' ...
<DefaultClassOptions, ImageName("BO_Employee")>
Public Class Employee
Implements INotifyPropertyChanged
Private _id As Integer
<Browsable(False)>
Public Property Id() As Integer
Get
Return _id
End Get
Protected Set(ByVal value As Integer)
If _id <> value Then
_id = value
OnPropertyChanged()
End If
End Set
End Property
Private _firstName As String
Public Property FirstName() As String
Get
Return _firstName
End Get
Set(ByVal value As String)
If _firstName <> value Then
_firstName = value
OnPropertyChanged()
End If
End Set
End Property
Private _lastName As String
Public Property LastName() As String
Get
Return _lastName
End Get
Set(ByVal value As String)
If _lastName <> value Then
_lastName = value
OnPropertyChanged()
End If
End Set
End Property
Private _birthday? As Date
Public Property Birthday() As Date?
Get
Return _birthday
End Get
Set(ByVal value? As Date)
If Not _birthday.Equals(value) Then
_birthday = value
OnPropertyChanged()
End If
End Set
End Property
Private _tasks As List(Of Task)
Public Overridable Property Tasks() As List(Of Task)
Get
Return _tasks
End Get
Set(ByVal value As List(Of Task))
If _tasks IsNot value Then
_tasks = value
OnPropertyChanged()
End If
End Set
End Property
#Region "INotifyPropertyChanged members"
Public Event PropertyChanged As PropertyChangedEventHandler _
Implements INotifyPropertyChanged.PropertyChanged
Protected Sub OnPropertyChanged( _
<CallerMemberName> Optional propertyName As String = Nothing)
Dim args As New PropertyChangedEventArgs(propertyName)
RaiseEvent PropertyChanged(Me, args)
End Sub
#End Region
End Class
using System.ComponentModel;
using System.Runtime.CompilerServices;
using DevExpress.Persistent.Base;
using DevExpress.ExpressApp.DC;
// ...
[DefaultClassOptions, ImageName("BO_Task")]
public class Task : INotifyPropertyChanged
{
private int id;
[Browsable(false)]
public int Id {
get { return id; }
protected set {
if (id != value) {
id = value;
OnPropertyChanged();
}
}
}
private string subject;
public string Subject {
get { return subject; }
set {
if (subject != value) {
subject = value;
OnPropertyChanged();
}
}
}
private string description;
[FieldSize(FieldSizeAttribute.Unlimited)]
public string Description {
get { return description; }
set {
if (description != value) {
description = value;
OnPropertyChanged();
}
}
}
private Employee assignedTo;
public virtual Employee AssignedTo {
get { return assignedTo; }
set {
if (assignedTo != value) {
assignedTo = value;
OnPropertyChanged();
}
}
}
#region INotifyPropertyChanged members
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null) {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
Imports System.ComponentModel
Imports System.Runtime.CompilerServices
Imports DevExpress.Persistent.Base
Imports DevExpress.ExpressApp.DC
' ...
<DefaultClassOptions, ImageName("BO_Task")>
Public Class Task
Implements INotifyPropertyChanged
Private _id As Integer
<Browsable(False)>
Public Property Id() As Integer
Get
Return _id
End Get
Protected Set(ByVal value As Integer)
If _id <> value Then
_id = value
OnPropertyChanged()
End If
End Set
End Property
Private _subject As String
Public Property Subject() As String
Get
Return _subject
End Get
Set(ByVal value As String)
If _subject <> value Then
_subject = value
OnPropertyChanged()
End If
End Set
End Property
Private _description As String
<FieldSize(FieldSizeAttribute.Unlimited)>
Public Property Description() As String
Get
Return _description
End Get
Set(ByVal value As String)
If _description <> value Then
_description = value
OnPropertyChanged()
End If
End Set
End Property
Private _assignedTo As Employee
Public Overridable Property AssignedTo() As Employee
Get
Return _assignedTo
End Get
Set(ByVal value As Employee)
If _assignedTo IsNot value Then
_assignedTo = value
OnPropertyChanged()
End If
End Set
End Property
#Region "INotifyPropertyChanged members"
Public Event PropertyChanged As PropertyChangedEventHandler _
Implements INotifyPropertyChanged.PropertyChanged
Protected Sub OnPropertyChanged( _
<CallerMemberName> Optional propertyName As String = Nothing)
Dim args As New PropertyChangedEventArgs(propertyName)
RaiseEvent PropertyChanged(Me, args)
End Sub
#End Region
End Class
该INotifyPropertyChanged的接口允许时,他们的属性值改变了你接收来自业务类的通知。
在此代码中,您会看到使用会影响UI生成的数据注释-DefaultClassOptionsAttribute,ImageNameAttribute和FieldSizeAttribute以及标准的.NET Browsable属性。结果,将创建Employee和Task导航项,将使用内置图像库中的图标,将为Task.Description属性显示多行编辑器,并且服务ID属性在UI中不可见。
您可以使用EF Power Tools来对现有数据库进行反向工程,而无需手动编写代码。
实现以下DbContext后代。
using System.Data.Entity;
// ...
public class MyDbContext : DbContext {
public MyDbContext(string connectionString) : base(connectionString) { }
public DbSet<Employee> Employees { get; set; }
public DbSet<Task> Tasks { get; set; }
}
Imports System.Data.Entity
// ...
Public Class MyDbContext
Inherits DbContext
Public Sub New(ByVal connectionString As String)
MyBase.New(connectionString)
End Sub
Private privateEmployees As DbSet(Of Employee)
Public Property Employees() As DbSet(Of Employee)
Get
Return privateEmployees
End Get
Set(ByVal value As DbSet(Of Employee))
privateEmployees = value
End Set
End Property
Private privateTasks As DbSet(Of Task)
Public Property Tasks() As DbSet(Of Task)
Get
Return privateTasks
End Get
Set(ByVal value As DbSet(Of Task))
privateTasks = value
End Set
End Property
End Class
请注意,MyDBContext类应实现一个带有connectionString字符串参数的构造函数。EFObjectSpaceProvider对象空间提供程序将在内部调用此构造函数。
若要使用EFObjectSpace实例访问应用程序中的数据,请修改WinApplication.cs(WinApplication.vb)和WebApplication.cs(WebApplication.vb)文件中的CreateDefaultObjectSpaceProvider方法的默认实现。有关此代码的详细信息,请参阅“使用实体框架数据模型”主题。
using DevExpress.ExpressApp.DC;
using DevExpress.ExpressApp.EF;
// ...
protected override void CreateDefaultObjectSpaceProvider(CreateCustomObjectSpaceProviderEventArgs args) {
args.ObjectSpaceProvider = new EFObjectSpaceProvider(typeof(MyDbContext), args.ConnectionString);
}
Imports DevExpress.ExpressApp.DC
Imports DevExpress.ExpressApp.EF
' ...
Protected Overrides Sub CreateDefaultObjectSpaceProvider( _
ByVal args As CreateCustomObjectSpaceProviderEventArgs)
args.ObjectSpaceProvider = New EFObjectSpaceProvider(GetType(MyDbContext), args.ConnectionString)
End Sub
若要连接为数据模型生成的数据库,请在代码中指定XafApplication.ConnectionString属性,或使用WinForms和ASP.NET应用程序项目中的App.config和Web.config文件中的相应选项。有关详细信息,请参阅“将XAF应用程序连接到数据库提供程序”主题。
现在,您可以同时运行Windows窗体和ASP.NET应用程序。您将看到为您的数据模型自动生成了一个UI。
若要学习如何用预定义的数据填充数据库,请参阅“如何:为实体框架数据模型提供初始数据”主题。