One day I decided to build this nice multi-tier application using L2S and WCF. The simplified model is : DataBase->L2S->Wrapper(DTO)->Client Application. The communication between Client and Database is achieved by using Data Transfer Objects which contain entity objects as their properties.
abstract public class BaseObject
{
public virtual IccSystem.iccObjectTypes ObjectICC_Type
{
get { return IccSystem.iccObjectTypes.unknownType; }
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage = "_ID", AutoSync = AutoSync.OnInsert, DbType = "BigInt NOT NULL IDENTITY", IsPrimaryKey = true, IsDbGenerated = true)]
[global::System.Runtime.Serialization.DataMemberAttribute(Order = 1)]
public virtual long ID
{
//get;
//set;
get
{
return _ID;
}
set
{
_ID = value;
}
}
}
[DataContract]
public class BaseObjectWrapper<T> where T : BaseObject
{
#region Fields
private T _DBObject;
#endregion
#region Properties
[DataMember]
public T Entity
{
get { return _DBObject; }
set { _DBObject = value; }
}
#endregion
}
Pretty simple, isn't it?. Here's the catch. Each one of the mapped classes contains ID property itself so I decided to override it like this
[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.Divisions")]
[global::System.Runtime.Serialization.DataContractAttribute()]
public partial class Division : INotifyPropertyChanging, INotifyPropertyChanged
{
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_ID", AutoSync=AutoSync.OnInsert, DbType="BigInt NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)]
[global::System.Runtime.Serialization.DataMemberAttribute(Order=1)]
public override long ID
{
get
{
return this._ID;
}
set
{
if ((this._ID != value))
{
this.OnIDChanging(value);
this.SendPropertyChanging();
this._ID = value;
this.SendPropertyChanged("ID");
this.OnIDChanged();
}
}
}
}
Wrapper for division is pretty straightforward as well:
public class DivisionWrapper : BaseObjectWrapper<Division>
{
}
It worked pretty well as long as I kept ID values at mapped class and its BaseObject class the same(that's not very good approach, I know, but still) but then this happened:
private CentralDC _dc;
public bool UpdateDivision(ref DivisionWrap开发者_运维问答per division)
{
DivisionWrapper tempWrapper = division;
if (division.Entity == null)
{
return false;
}
try
{
Table<Division> table = _dc.Divisions;
var q = table.Where(o => o.ID == tempWrapper.Entity.ID);
if (q.Count() == 0)
{
division.Entity._errorMessage = "Unable to locate entity with id " + division.Entity.ID.ToString();
return false;
}
var realEntity = q.First();
realEntity = division.Entity;
_dc.SubmitChanges();
return true;
}
catch (Exception ex)
{
division.Entity._errorMessage = ex.Message;
return false;
}
}
When trying to enumerate over the in-memory query the following exception occurred: Class member BaseObject.ID is unmapped. Although I'm stating the type and overriding the ID property L2S fails to work. Any suggestions?
Suppose I found the problem. When writing
var q = table.Where(o => o.ID == tempWrapper.Entity.ID);
the compiler implies that the object is of BaseObject type and therefore tries to get its ID value from the BaseObject mapping and it's unmapped. The problem seems to be resolved by explicitly declaring the type:
var q = from Division div in _dc.GetTable<Division>()
where div.ID == tempWrapper.Entity.ID
select div;
精彩评论