数据库
首页 > 数据库> > CodeGo.net>如何避免将数据库表映射到数据协定时创建其他类?

CodeGo.net>如何避免将数据库表映射到数据协定时创建其他类?

作者:互联网

我有数据合同:

[DataContract]
public class Entity
{
   [DataMember]
   public int? Temp
   {
       get;
       set;
   }
   //other properties
}

我需要基于数据库表信息创建实体对象.我必须使用SqlDataReader(要求),然后将列映射到实体属性.我创建了一个辅助类,该类使用Description属性描述映射:

public class Entity
{
   [Description("TempColumnName")]
   public int? Temp
   {
       get;
       set;
   }
   //other properties
}

在这种情况下,如何避免创建其他类?我认为使用数据协定属性名称或用其他属性修饰数据协定是一个坏主意.你有什么建议吗?

解决方法:

您的数据合同代表您的服务向外界公开的公共API.一旦您的服务开始被客户使用,您就希望避免对此合同做出重大更改-特别是如果您的服务被超出您控制范围的客户使用.当然,如果您的服务仅用于“内部”使用,那么您对此会有一定的灵活性.

遵循“从程序抽象到而非实现”的理念,WCF服务的数据(和服务)合同在面向服务的上下文中提供抽象,类似于面向对象的世界中的接口.

如果您使用.dll共享数据合同,那么我认为-您无法避免需要单独的类来表示服务数据合同和数据模型的事实.使用像AutoMapper这样的映射工具,可以大大减少转换代码的数量.如果您试图在数据合同中增加额外的信息(例如通过数据成员上的属性),则最终会将有关数据访问方法的信息泄漏到已发布的二进制文件中.如果将来您切换到另一种数据访问方法-甚至NoSQL数据库,会发生什么?您对数据合同的更改可能会使用较旧版本的二进制文件破坏现有的客户端.

在提出替代方案之前-让我说以上是我在所有情况下都会做的事情.您的数据模型和服务API代表了根本不同的野兽,由于不同的因素,它们将彼此独立地变化.尽管它们看起来常常很相似,但使用和更改的上下文却完全不同.

现在要入侵…

如果要通过MEX端点发布服务API,则当Visual Studio(或真正的svcutil.exe)生成代理时,客户端将获得其自己的服务和数据合同版本.在服务方面,您可以执行以下操作:

[DataContract]
public class Entity
{
    [DataMember]
    public int? Temp { get; set; }

    [Description]
    public int? DbTemp { get; set; }

    [OnSerializing()]
    internal void OnSerializingMethod(StreamingContext context)
    {
        Temp = DbTemp;
    }
}

从数据库中填充实体实例时,将设置DbTemp属性.仅当实例进行序列化以准备发送到客户端时,才会填充Temp属性.

当您的客户端从MEX端点生成代理协议和数据合同时,实体数据合同如下所示:

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="Entity", Namespace="http://schemas.datacontract.org/2004/07/WcfService1")]
[System.SerializableAttribute()]
public partial class Entity : object, System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged {

    [System.NonSerializedAttribute()]
    private System.Runtime.Serialization.ExtensionDataObject extensionDataField;

    [System.Runtime.Serialization.OptionalFieldAttribute()]
    private System.Nullable<int> TempField;

    [global::System.ComponentModel.BrowsableAttribute(false)]
    public System.Runtime.Serialization.ExtensionDataObject ExtensionData {
        get {
            return this.extensionDataField;
        }
        set {
            this.extensionDataField = value;
        }
    }

    [System.Runtime.Serialization.DataMemberAttribute()]
    public System.Nullable<int> Temp {
        get {
            return this.TempField;
        }
        set {
            if ((this.TempField.Equals(value) != true)) {
                this.TempField = value;
                this.RaisePropertyChanged("Temp");
            }
        }
    }

    public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChanged(string propertyName) {
        System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
        if ((propertyChanged != null)) {
            propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
        }
    }
}

不嗅探您的数据访问实现!

最后,请注意,您可以通过发布.dll来实现上述技巧-您只需发布包含上面“精简”数据协定的.dll.但是,这意味着您必须有效地管理两个不同版本的Entity-您的服务内部使用的版本以及已发布的.dll中的版本.如果这些不同步-祝您调试顺利!

标签:sqldatareader,wcf,c,net
来源: https://codeday.me/bug/20191122/2060976.html