我可以使用映射到 ef 4.1 中两个不同表的一个外键列动态填充关系数据吗?

发布于 2024-12-14 20:18:17 字数 3370 浏览 1 评论 0原文

我有 ac# .net 4 wcf ria 服务暴露给 silverlight 4 客户端,首先使用 linq to ef 代码。

DbContext:

public class TableA
{
    public long TableAId {get; set;}
    public string LinkedTableType {get; set;}
    public long LinkedTableId {get; set;}

    public virtual TableB TableB { get; set; }
    public virtual TableC TableC { get; set; }
}

public class TableB
{
    public long TableBId {get; set;}
    public string TableB_1 {get; set;}

    public long ChildTableAId {get; set;}
    [ForeignKey("ChildTableAId")]
    public virtual TableA TableA {get; set;}
}

public class TableC
{
    public long TableCId {get; set;}
    public string TableC_1 {get; set;}
    public string TableC_2 {get; set;}
}

TableA.LinkedTableId 是一个外键,根据 LinkedTableType 的值,分别通过 TableBId 或 TableCId 与 TableB 或 TableC 相关。 例如,LinkedTableType 可以是“B”或“C”。

我在此处阅读了问题,但我想防止来自 TableA -> 的 ef 循环引用表B->表A->表 B. 请注意,真实数据不会发生这种情况;如果TableA 中的一行指向TableB 中的一行,则TableB 中ChildTableAId 指向的TableA 中的行永远不应该指向TableB,而只能指向TableC。

域服务:

[MetadataTypeAttribute(typeof(TableA.TableAMetadata))]
public partial class TableA
{
    internal sealed class TableAMetadata
        {
            private TableAMetadata()
            {
            }

            public long TableAId { get; set; }

            [Include]
            public TableB TableB { get; set; }

            [Include]
            public TableC TableC { get; set; }
        }
}

public partial class TableB
{
    internal sealed class TableBMetadata
    {
        private TableBMetadata()
        {
        }

        public long TableBId { get; set; }

        public string TableB_1 { get; set; }

        public long ChildTableAId { get; set; }

        [Include]
        public TableA TableA { get; set; }
    }
}

[EnableClientAccess]
public partial class Sample1DomainService : LinqToEntitiesDomainService<Sample1Entities>
{
    public IQueryable<TableA> GetTableA()
    {
        return this.ObjectContext.TableA
            .Include("TableB");
            .Include("TableC");
    }
}

我可以毫无错误地编译域服务 (Sample1.RIAServices.Web),但 wcf ria 服务 silverlight 库 (Sample1.RIAServices) 失败并出现以下编译器错误:

类型“Sample1.RIAServices.Web.TableA”的关联元数据类型 包含以下未知属性或字段:TableB、TableC。 请确保这些成员的姓名与 主要类型的属性。

如何在服务器端填充 TableB 或 TableC,以便它们可以直接在 wcf ria 客户端上使用? 是否可以通过在 DbContext 上的重写 OnModelCreating 方法中指定自定义关系映射和\或在 wcf ria 域服务中指定自定义 linq 查询来实现? 如果是这样,怎么办?

例如,这就是我在客户端所期望的:

IEnumerable<TableA> tableA = MyDbContext.TableA;

foreach (TableA _tableA in tableA)
{
    if (_tableA.LinkedTableType == "B")
    {
        Assert.IsNotNull(_tableA.TableB);
        Assert.IsNull(_tableA.TableC);
    }
    else if (_tableA.LinkedTableType == "C")
    {
        Assert.IsNotNull(_tableA.TableC);
        Assert.IsNull(_tableA.TableB);
    }
    else
    {
        Assert.IsNull(_tableA.TableB);
        Assert.IsNull(_tableA.TableC);
    }
}

我想在服务器端执行此操作以支持对 TableA 中的记录进行分页,而不必加载整个 TableB 和 TableC 以确保外部表存在。

有没有更好的数据库设计? 请注意,在我的实际数据库设计中,TableB 中有大约 10 列,TableC 中有 6 列。表B 和表C 中的列并不相似。 我希望保持设计足够的灵活性,以便我可以轻松添加对更多“链接”表(例如 TableD、TableE、TableF 等)的支持。

谢谢。

I have a c# .net 4 wcf ria service exposed to a silverlight 4 client, using linq to ef code first.

DbContext:

public class TableA
{
    public long TableAId {get; set;}
    public string LinkedTableType {get; set;}
    public long LinkedTableId {get; set;}

    public virtual TableB TableB { get; set; }
    public virtual TableC TableC { get; set; }
}

public class TableB
{
    public long TableBId {get; set;}
    public string TableB_1 {get; set;}

    public long ChildTableAId {get; set;}
    [ForeignKey("ChildTableAId")]
    public virtual TableA TableA {get; set;}
}

public class TableC
{
    public long TableCId {get; set;}
    public string TableC_1 {get; set;}
    public string TableC_2 {get; set;}
}

TableA.LinkedTableId is a foregin key that relates to either TableB or TableC by TableBId or TableCId respectively, depending on the value of LinkedTableType.
For example, LinkedTableType can be "B" or "C".

I read the question here but I want to prevent an ef circular reference from TableA -> TableB -> TableA -> TableB.
Note that this cannot happen with real data; If a row in TableA points to a row in TableB, the row in TableA that TableB points to by ChildTableAId should never point back to TableB, only to TableC.

Domain Service:

[MetadataTypeAttribute(typeof(TableA.TableAMetadata))]
public partial class TableA
{
    internal sealed class TableAMetadata
        {
            private TableAMetadata()
            {
            }

            public long TableAId { get; set; }

            [Include]
            public TableB TableB { get; set; }

            [Include]
            public TableC TableC { get; set; }
        }
}

public partial class TableB
{
    internal sealed class TableBMetadata
    {
        private TableBMetadata()
        {
        }

        public long TableBId { get; set; }

        public string TableB_1 { get; set; }

        public long ChildTableAId { get; set; }

        [Include]
        public TableA TableA { get; set; }
    }
}

[EnableClientAccess]
public partial class Sample1DomainService : LinqToEntitiesDomainService<Sample1Entities>
{
    public IQueryable<TableA> GetTableA()
    {
        return this.ObjectContext.TableA
            .Include("TableB");
            .Include("TableC");
    }
}

I can compile the domain service (Sample1.RIAServices.Web) without errors, but the wcf ria service silverlight library (Sample1.RIAServices) fails with the following compiler error:

The associated metadata type for type 'Sample1.RIAServices.Web.TableA'
contains the following unknown properties or fields: TableB, TableC.
Please make sure that the names of these members match the names of
the properties on the main type.

How do I populate TableB or TableC on the server side so that they are directly available on the wcf ria client?
Is this possible by specifying a custom relational mapping in the overriden OnModelCreating method on the DbContext and\or specifying a custom linq query in the wcf ria domain service?
If so, how?

For example, this is what I would expect on the client side:

IEnumerable<TableA> tableA = MyDbContext.TableA;

foreach (TableA _tableA in tableA)
{
    if (_tableA.LinkedTableType == "B")
    {
        Assert.IsNotNull(_tableA.TableB);
        Assert.IsNull(_tableA.TableC);
    }
    else if (_tableA.LinkedTableType == "C")
    {
        Assert.IsNotNull(_tableA.TableC);
        Assert.IsNull(_tableA.TableB);
    }
    else
    {
        Assert.IsNull(_tableA.TableB);
        Assert.IsNull(_tableA.TableC);
    }
}

I want to do this on the server side to support paging through records in TableA and not have to load the entire TableB and TableC to ensure that the foreign tables exists.

If there a better database design?
Note that in my real database design there are about 10 columns in TableB and 6 columns in TableC. The columns in TableB and TableC are not similar.
I'd like to keep the design flexible enough so that I can easily add support for more "linked" tables (ex. TableD, TableE, TableF, etc.)

Thank you.

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

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

发布评论

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

评论(1

没有伤那来痛 2024-12-21 20:18:17

我实际上通过执行以下操作解决了我的问题:
1.删​​除LinkedTableId
2.添加可为空的外键TableA.TableBId和TableA.TableCId

这篇文章对我帮助很大。 :)

I actually resolved my problem by doing the following:
1. delete LinkedTableId
2. add nullable foreign keys TableA.TableBId and TableA.TableCId

This post helped me lot. :)

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