在Linq2SQL中创建条件关系

时间:2011-09-14 13:05:54

标签: linq-to-sql

我在旧数据库系统上使用linq2sql。在这个系统中有三个表,Invoices,Users和SignupUsers。 Invoices表有一个UID字段,通常引用Users表上的UID键。但是,它还有一个IsSignup位字段,指示UID字段应该引用SignupUsers表上的UID键。

我并不关心与SignupUsers表的关系,但我们确实遇到一个问题,即在使用linq2sql实体时很容易忘记检查“IsSignup”值。我想根据IsSignup位字段使实体中的Invoices-> Users关系成为可能。

我尝试了几种方法。首先我尝试设置OnLoaded:

public partial class Invoice
{
    partial void OnLoaded()
    {
        if (IsSignup)
        {
            InvoiceUser = null;
        }
    }
}

这会失败,因为它会在将发票保存回来时尝试将UID字段实际设置为null - 这是我们无法做到的。

我使用DataLoadOptions进行了调查,但无法找到使其工作的方法。

我可以更改InvoiceUsers属性getter,但每次dbml更改时都会被覆盖。

我在这里运气不好吗?

1 个答案:

答案 0 :(得分:0)

我会在这里提出解决方案,但仍希望有人能提出更好的解决方案。

我正在使用LINQ to SQL templates for T4来生成代码。我进入了.tt文件,找到了这个特定的.dbml文件,找到了生成关系属性的部分。然后我攻击了一个“if”语句,如果它应用于这个特定的关系,它就修改了属性:

    <#=code.Format(association.MemberAttributes)#><#=association.Type.Name#> <#=association.Member#>
    {
        get {
            <#if(association.Name == "InvoiceUser_Invoice"){#>
                            //HACK IN THE .TT FILE TO ALWAYS INCLUDE THIS CONDITIONAL RELATIONSHIP
            if(IsSignup){return null;}
            <#}#>
            <#if (needsSerializationFlag && serialization) {#>
            if (serializing && !<#=association.Storage#>.HasLoadedOrAssignedValue) {
                return null;
            }
            <#}#>
            return <#=association.Storage#>.Entity;
        }

这使得该特定属性的生成代码符合要求:

    [Association(Name=@"InvoiceUser_Invoice", Storage=@"_InvoiceUser", ThisKey=@"UID", OtherKey=@"UID", IsForeignKey=true)]
    public InvoiceUser InvoiceUser
    {
        get {
            //HACK IN THE .TT FILE TO ALWAYS INCLUDE THIS CONDITIONAL RELATIONSHIP
                            if(IsSignup){return null;}
                            return _InvoiceUser.Entity;
        }
        set {
            InvoiceUser previousValue = _InvoiceUser.Entity;
            if ((previousValue != value) || (!_InvoiceUser.HasLoadedOrAssignedValue)) {
                SendPropertyChanging();
                if (previousValue != null) {
                    _InvoiceUser.Entity = null;
                    previousValue.Invoices.Remove(this);
                }
                _InvoiceUser.Entity = value;
                if (value != null) {
                    value.Invoices.Add(this);
                    _UID = value.UID;
                }
                else {
                    _UID = default(int);
                }
                SendPropertyChanged("InvoiceUser");
            }
        }
    }

所以仍然是一个令人讨厌的黑客攻击,但它至少可以防止.dbml文件的更改删除所需的条件关系。