在一个项目中,我使用 LINQ to SQL 和 WCF。
我有以下单表继承:
当我调用GetMediaForItem
返回ItemMedia
(基类型)对象列表的 WCF 方法 () 时,我得到了异常A first chance exception of type 'System.Runtime.Serialization.SerializationException' occurred in System.Runtime.Serialization.dll
。
但是当我调用一个 WCF 方法 ( GetYouTubeVideosForItem
) 来返回一个YouTubeVideo
's 列表(派生类型之一)时,它工作正常。
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class MediaService : IMediaService
{
...
// this throws a System.Runtime.Serialization.SerializationException
public List<ItemMedia> GetMediaForItem(int itemId)
{
using (var context = _db.CreateContext())
{
context.DeferredLoadingEnabled = false;
return (from i in context.ItemMedias
where i.ItemID == itemId
orderby i.Order
select i).ToList();
}
}
// this works fine
public List<YouTubeVideo> GetYouTubeVideosForItem(int itemId)
{
using (var context = _db.CreateContext())
{
context.DeferredLoadingEnabled = false;
return (from i in context.ItemMedias.OfType<YouTubeVideo>()
where i.ItemID == itemId
orderby i.Order
select i).ToList();
}
}
}
服务接口:
[ServiceContract]
public interface IMediaService
{
[OperationContract]
[WebInvoke(
Method = "GET",
UriTemplate = "Media?itemId={itemId}",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare
)]
List<ItemMedia> GetMediaForItem(int itemId);
[OperationContract]
[WebInvoke(
Method = "GET",
UriTemplate = "YouTubeVideos?itemId={itemId}",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare
)]
List<YouTubeVideo> GetYouTubeVideosForItem(int itemId);
}
以下是生成的模型:
[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.ItemMedia")]
[global::System.Data.Linq.Mapping.InheritanceMappingAttribute(Code="media", Type=typeof(ItemMedia), IsDefault=true)]
[global::System.Data.Linq.Mapping.InheritanceMappingAttribute(Code="video", Type=typeof(YouTubeVideo))]
[global::System.Data.Linq.Mapping.InheritanceMappingAttribute(Code="image", Type=typeof(Image))]
public partial class ItemMedia : INotifyPropertyChanging, INotifyPropertyChanged
{
private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);
private int _ID;
private int _ItemID;
private string _MediaType;
private int _Order;
private System.Nullable<System.DateTime> _AddedOn;
private System.Nullable<int> _AddedBy;
private System.Nullable<System.DateTime> _ChangedOn;
private System.Nullable<int> _ChangedBy;
private EntityRef<Item> _Item;
#region Extensibility Method Definitions
partial void OnLoaded();
partial void OnValidate(System.Data.Linq.ChangeAction action);
partial void OnCreated();
partial void OnIDChanging(int value);
partial void OnIDChanged();
partial void OnItemIDChanging(int value);
partial void OnItemIDChanged();
partial void OnMediaTypeChanging(string value);
partial void OnMediaTypeChanged();
partial void OnOrderChanging(int value);
partial void OnOrderChanged();
partial void OnAddedOnChanging(System.Nullable<System.DateTime> value);
partial void OnAddedOnChanged();
partial void OnAddedByChanging(System.Nullable<int> value);
partial void OnAddedByChanged();
partial void OnChangedOnChanging(System.Nullable<System.DateTime> value);
partial void OnChangedOnChanged();
partial void OnChangedByChanging(System.Nullable<int> value);
partial void OnChangedByChanged();
#endregion
public ItemMedia()
{
this._Item = default(EntityRef<Item>);
OnCreated();
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_ID", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)]
public int ID
{
get
{
return this._ID;
}
set
{
if ((this._ID != value))
{
this.OnIDChanging(value);
this.SendPropertyChanging();
this._ID = value;
this.SendPropertyChanged("ID");
this.OnIDChanged();
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_ItemID", DbType="Int")]
public int ItemID
{
get
{
return this._ItemID;
}
set
{
if ((this._ItemID != value))
{
if (this._Item.HasLoadedOrAssignedValue)
{
throw new System.Data.Linq.ForeignKeyReferenceAlreadyHasValueException();
}
this.OnItemIDChanging(value);
this.SendPropertyChanging();
this._ItemID = value;
this.SendPropertyChanged("ItemID");
this.OnItemIDChanged();
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_MediaType", DbType="VarChar(10)", IsDiscriminator=true)]
public string MediaType
{
get
{
return this._MediaType;
}
set
{
if ((this._MediaType != value))
{
this.OnMediaTypeChanging(value);
this.SendPropertyChanging();
this._MediaType = value;
this.SendPropertyChanged("MediaType");
this.OnMediaTypeChanged();
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Name="[Order]", Storage="_Order", DbType="Int NOT NULL")]
public int Order
{
get
{
return this._Order;
}
set
{
if ((this._Order != value))
{
this.OnOrderChanging(value);
this.SendPropertyChanging();
this._Order = value;
this.SendPropertyChanged("Order");
this.OnOrderChanged();
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_AddedOn", DbType="DateTime")]
public System.Nullable<System.DateTime> AddedOn
{
get
{
return this._AddedOn;
}
set
{
if ((this._AddedOn != value))
{
this.OnAddedOnChanging(value);
this.SendPropertyChanging();
this._AddedOn = value;
this.SendPropertyChanged("AddedOn");
this.OnAddedOnChanged();
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_AddedBy", DbType="Int")]
public System.Nullable<int> AddedBy
{
get
{
return this._AddedBy;
}
set
{
if ((this._AddedBy != value))
{
this.OnAddedByChanging(value);
this.SendPropertyChanging();
this._AddedBy = value;
this.SendPropertyChanged("AddedBy");
this.OnAddedByChanged();
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_ChangedOn", DbType="DateTime")]
public System.Nullable<System.DateTime> ChangedOn
{
get
{
return this._ChangedOn;
}
set
{
if ((this._ChangedOn != value))
{
this.OnChangedOnChanging(value);
this.SendPropertyChanging();
this._ChangedOn = value;
this.SendPropertyChanged("ChangedOn");
this.OnChangedOnChanged();
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_ChangedBy", DbType="Int")]
public System.Nullable<int> ChangedBy
{
get
{
return this._ChangedBy;
}
set
{
if ((this._ChangedBy != value))
{
this.OnChangedByChanging(value);
this.SendPropertyChanging();
this._ChangedBy = value;
this.SendPropertyChanged("ChangedBy");
this.OnChangedByChanged();
}
}
}
[global::System.Data.Linq.Mapping.AssociationAttribute(Name="Item_ItemMedia", Storage="_Item", ThisKey="ItemID", OtherKey="ID", IsForeignKey=true)]
public Item Item
{
get
{
return this._Item.Entity;
}
set
{
Item previousValue = this._Item.Entity;
if (((previousValue != value)
|| (this._Item.HasLoadedOrAssignedValue == false)))
{
this.SendPropertyChanging();
if ((previousValue != null))
{
this._Item.Entity = null;
previousValue.ItemMedias.Remove(this);
}
this._Item.Entity = value;
if ((value != null))
{
value.ItemMedias.Add(this);
this._ItemID = value.ID;
}
else
{
this._ItemID = default(int);
}
this.SendPropertyChanged("Item");
}
}
}
public event PropertyChangingEventHandler PropertyChanging;
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void SendPropertyChanging()
{
if ((this.PropertyChanging != null))
{
this.PropertyChanging(this, emptyChangingEventArgs);
}
}
protected virtual void SendPropertyChanged(String propertyName)
{
if ((this.PropertyChanged != null))
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public partial class YouTubeVideo : ItemMedia
{
private string _YouTubeVideoID;
#region Extensibility Method Definitions
partial void OnLoaded();
partial void OnValidate(System.Data.Linq.ChangeAction action);
partial void OnCreated();
partial void OnYouTubeVideoIDChanging(string value);
partial void OnYouTubeVideoIDChanged();
#endregion
public YouTubeVideo()
{
OnCreated();
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_YouTubeVideoID", DbType="NVarChar(15)")]
public string YouTubeVideoID
{
get
{
return this._YouTubeVideoID;
}
set
{
if ((this._YouTubeVideoID != value))
{
this.OnYouTubeVideoIDChanging(value);
this.SendPropertyChanging();
this._YouTubeVideoID = value;
this.SendPropertyChanged("YouTubeVideoID");
this.OnYouTubeVideoIDChanged();
}
}
}
}
public partial class Image : ItemMedia
{
private string _ImageName;
private string _ImageData;
#region Extensibility Method Definitions
partial void OnLoaded();
partial void OnValidate(System.Data.Linq.ChangeAction action);
partial void OnCreated();
partial void OnImageNameChanging(string value);
partial void OnImageNameChanged();
partial void OnImageDataChanging(string value);
partial void OnImageDataChanged();
#endregion
public Image()
{
OnCreated();
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_ImageName", DbType="NVarChar(MAX)")]
public string ImageName
{
get
{
return this._ImageName;
}
set
{
if ((this._ImageName != value))
{
this.OnImageNameChanging(value);
this.SendPropertyChanging();
this._ImageName = value;
this.SendPropertyChanged("ImageName");
this.OnImageNameChanged();
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_ImageData", DbType="NVarChar(MAX)")]
public string ImageData
{
get
{
return this._ImageData;
}
set
{
if ((this._ImageData != value))
{
this.OnImageDataChanging(value);
this.SendPropertyChanging();
this._ImageData = value;
this.SendPropertyChanged("ImageData");
this.OnImageDataChanged();
}
}
}
}