MVVM 轻型数据网格从两个关系数据库表加载

发布于 2024-09-10 03:59:18 字数 210 浏览 3 评论 0原文

如何使用 MVVM light 加载带有两个相关表的 DataGrid,我正在使用 .NET RIA 和 silverlight 4。

例如,如果我的数据表是:

userInfo- 用户 ID、姓名、地址 ID
地址 - AddressID、StreetName、Zip

如何创建显示 [Name、StreetName、ZIp] 的数据网格

How to Load DataGrid with two related tables using MVVM light, I am using .NET RIA and silverlight 4.

for example if my data tables are:

userInfo-
userID, Name, AddressID
Address -
AddressID, StreetName, Zip

how can i create datagrid that displays [Name, StreetName, ZIp]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

日暮斜阳 2024-09-17 03:59:18

首先,您必须在 DomainService 类的 UserInfo 的 GetQuery 中包含地址表,如下所示...

  [Query]
  public IQueryable<UserInfo> GetUserInfos()
    {
        return this.ObjectContext.UserInfos.Include("Address");
    }

然后在元数据文件中,您必须在“

  [Include]
        public Addresses Address{ get; set; }
        public int AddressID { get; set; }

立即构建解决方案”上方添加 [Include]。
现在在 Xaml 中你可以像这样使用

  <sdk:DataGrid ItemsSource="{Binding UserList, Mode=TwoWay}" SelectedItem="{Binding CurrentUser, Mode=TwoWay}" Margin="0,0,0,2" AutoGenerateColumns="False">
        <sdk:DataGrid.Columns>
            <sdk:DataGridTextColumn Header="Name" Binding="{Binding Path=Name}"/>
            <sdk:DataGridTextColumn Header="Street Name" Binding="{Binding Path=Address.StreetName}"/>
            <sdk:DataGridTextColumn Header="Zip" Binding="{Binding Path=Address.Zip}"/>
        </sdk:DataGrid.Columns>

    </sdk:DataGrid>

First of all you have to include Address table in GetQuery of UserInfo in your DomainService class like below...

  [Query]
  public IQueryable<UserInfo> GetUserInfos()
    {
        return this.ObjectContext.UserInfos.Include("Address");
    }

then in the metadata file u have to add [Include] just above the

  [Include]
        public Addresses Address{ get; set; }
        public int AddressID { get; set; }

Now Build the solution.
Now in the Xaml you can use like this

  <sdk:DataGrid ItemsSource="{Binding UserList, Mode=TwoWay}" SelectedItem="{Binding CurrentUser, Mode=TwoWay}" Margin="0,0,0,2" AutoGenerateColumns="False">
        <sdk:DataGrid.Columns>
            <sdk:DataGridTextColumn Header="Name" Binding="{Binding Path=Name}"/>
            <sdk:DataGridTextColumn Header="Street Name" Binding="{Binding Path=Address.StreetName}"/>
            <sdk:DataGridTextColumn Header="Zip" Binding="{Binding Path=Address.Zip}"/>
        </sdk:DataGrid.Columns>

    </sdk:DataGrid>
方觉久 2024-09-17 03:59:18

这里有几种可能的方法。我将解释我想到的两个问题。首先,使用数据库中已定义的关系。第二种是通过自定义模型类返回。

选项 1:
我假设您已经从 Web 项目上的数据库创建了一个实体框架模型(具有关系),并创建了 DomainService 来托管该模型。 !!!创建模型时要做的一个关键是为模型创建元数据类! (我在前几次错过了这一点,修改模型的行为至关重要,就像您在这里所需要的那样)

在元数据模型中,您将找到关联属性,并用 [Ininclude ] 属性。这是我从另一个带有 WorklanDetail 的项目中获得的示例,我想在其中返回关联的分配:

[MetadataTypeAttribute(typeof(WorkplanDetailMetadata))]
public partial class WorkplanDetail
{
    internal sealed class WorkplanDetailMetadata
    {
        [Include]
        public EntityCollection<Assignment> Assignments { get; set; }
    }
}

然后,您只需在 Silverlight 应用程序中引用该属性即可,并且您的地址数据可用。

要绑定单个实体(EntityReference,而不是集合),那么您只需使用属性来访问数据网格绑定上的子实体...例如:

Text="{Binding Path=Address.StreetName}"

这是我所知道的最简单的方法。

选项 2 需要创建您自己的自定义类(您必须至少有一个用 [Key] 属性装饰的属性,以便于与客户端之间的传输)。下面是一个我用来获取文件夹搜索结果信息的例子:

public class FolderSearchResult
{
    [Key]
    public string EFOLDERID { get; set; }
    public string Subject { get; set; }
    public string FolderName { get; set; }
}

关键是 EFOLDERID 属性具有 [Key] 属性,它唯一标识每个项目,就像数据库中的 PK 一样。

然后,在您的服务类中,您可以像这样返回这种类型:

public IEnumerable<FolderSearchResult> GetFolderResults(string search)
    {
        var query = from ge in this.ObjectContext.Generic_Engagement
                    from f in this.ObjectContext.eFolders
                    where ge.EFOLDERID == f.eFolderID &
                    f.eArchived == 0 &
                    f.eSubject.Contains(search) &

                    (from wp in this.ObjectContext.Workplans
                     where wp.EFOLDERID == f.eFolderID
                     select wp).Count() == 0 &

                     (from r in this.ObjectContext.Resources
                      where r.EFOLDERID == f.eFolderID
                      select r).Count() == 0

                    select new FolderSearchResult()
                      {
                        EFOLDERID = f.eFolderID,
                        FolderName = f.eFolderName,
                        Subject = f.eSubject
                      };
        return query.AsEnumerable<FolderSearchResult>();
    }

关于此方法的一些注意事项:

  1. 在我看来,当您不需要只读访问权限时,这种方法效果最好。如果您正在进行更新/插入/删除,请使用第一种方法。
  2. 当您需要在完全不同的数据源(可能是数据库中的用户 ID 和员工 ID,以及 Active Directory 中的显示名称、站点位置等)之间创建一些逻辑对象时,这非常有用。
  3. 通过这种方式更新是可能的,但您必须做更多的工作来分离您的项目并正确更新所有内容。

总之,我建议使用第一种方法,除非发生以下情况:您需要一个跨数据存储(单独的数据库源)的逻辑对象,或者您需要快速只读访问(例如下拉列表的 ItemSource 绑定) )。

根据我的经验,将排序和过滤逻辑卸载到服务器,即使以在内存中加载额外实体为代价,以便您的客户端可以保持快速,也会带来好处。在 CollectionViewSource 中使用本地排序或其他东西可以起到同样的作用,但其中的一些确实会开始降低应用程序的速度。

There are a couple approaches possible here. I will explain both that come to mind. First, is using a relationship already defined in your database. Second is to return via a custom model class.

Option 1:
I will assume you have created an Entity Framework Model (with a relationship) from your database on the Web Project and created the DomainService to host the Model. !!!One key to do when you create the model is to create meta-data classes for the models!!! (I missed this the first few times through, and it is critical to modify the behavior of your models, such as you are needing here)

Within the meta-data model, you will find the association property, and decorate it with the [Include] attribute. Here is an example I have from another project with a WorklanDetail, where I want to return the associated Assignments:

[MetadataTypeAttribute(typeof(WorkplanDetailMetadata))]
public partial class WorkplanDetail
{
    internal sealed class WorkplanDetailMetadata
    {
        [Include]
        public EntityCollection<Assignment> Assignments { get; set; }
    }
}

then, you can just reference the property in your Silverlight application, and viola your address data is available.

To bind a single Entity (EntityReference, not collection) then you will just use you property to access the sub-entity on your datagrid's binding... For exmaple:

Text="{Binding Path=Address.StreetName}"

That is the simplest method that I know of.

Option 2 requires creating your own custom class (you must at least have a property decorated with the [Key] attribute ot facilitate the transfer to/from the client). Here is an example, I have used to get foldersearch result information:

public class FolderSearchResult
{
    [Key]
    public string EFOLDERID { get; set; }
    public string Subject { get; set; }
    public string FolderName { get; set; }
}

The key being that the EFOLDERID propety has the [Key] attribute, which uniquely identifies each item just like a PK in a database.

Then in your service class you can return this kind of like this:

public IEnumerable<FolderSearchResult> GetFolderResults(string search)
    {
        var query = from ge in this.ObjectContext.Generic_Engagement
                    from f in this.ObjectContext.eFolders
                    where ge.EFOLDERID == f.eFolderID &
                    f.eArchived == 0 &
                    f.eSubject.Contains(search) &

                    (from wp in this.ObjectContext.Workplans
                     where wp.EFOLDERID == f.eFolderID
                     select wp).Count() == 0 &

                     (from r in this.ObjectContext.Resources
                      where r.EFOLDERID == f.eFolderID
                      select r).Count() == 0

                    select new FolderSearchResult()
                      {
                        EFOLDERID = f.eFolderID,
                        FolderName = f.eFolderName,
                        Subject = f.eSubject
                      };
        return query.AsEnumerable<FolderSearchResult>();
    }

Couple of notes about this approach:

  1. This works best in my opinion when you don't need Read-Only access. If you are doing updates/inserts/deletes use the first approach.
  2. This works well to help when you need to create some logical object between completely different data sources (maybe userid and employeeid from database, plus display name, site location, etc. from Active Directory).
  3. Updating this way is possible, but you must do a bit more work to separate out your items and update everything properly.

In summary, I would suggest using the first approach, unless the following occur: You need a logical object which crosses data-storage (separate db sources), or you need fast read-only access (such as ItemSource binding for drop-down list).

Offloading sorting and filtering logic to the server, even at the expense of additional entities loaded in memory so that your client can remain fast pays dividends in my experience. Using local sort in a CollectionViewSource or something can do the same, but just a few of these can really start slowing your application speed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文