无法手动修改LINQ to sql产生的类!

yuling_xia 2008-04-16 09:25:04
下面是一个linq to sql产生的Person类
#pragma warning disable 1591
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行库版本:2.0.50727.1433
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------

namespace MemberDll.Person
{
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Data;
using System.Collections.Generic;
using System.Reflection;
using System.Linq;
using System.Linq.Expressions;
using System.ComponentModel;
using System;


[System.Data.Linq.Mapping.DatabaseAttribute(Name="Member")]
public partial class PersonDataContext : System.Data.Linq.DataContext
{

private static System.Data.Linq.Mapping.MappingSource mappingSource = new AttributeMappingSource();

#region Extensibility Method Definitions
partial void OnCreated();
partial void InsertPerson(Person instance);
partial void UpdatePerson(Person instance);
partial void DeletePerson(Person instance);
#endregion

public PersonDataContext() :
base("", mappingSource)
{
OnCreated();
}

public PersonDataContext(string connection) :
base(connection, mappingSource)
{
OnCreated();
}

public PersonDataContext(System.Data.IDbConnection connection) :
base(connection, mappingSource)
{
OnCreated();
}

public PersonDataContext(string connection, System.Data.Linq.Mapping.MappingSource mappingSource) :
base(connection, mappingSource)
{
OnCreated();
}

public PersonDataContext(System.Data.IDbConnection connection, System.Data.Linq.Mapping.MappingSource mappingSource) :
base(connection, mappingSource)
{
OnCreated();
}

public System.Data.Linq.Table<Person> Person
{
get
{
return this.GetTable<Person>();
}
}
}

[Table(Name="dbo.Person")]
public partial class Person : INotifyPropertyChanging, INotifyPropertyChanged
{

private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);

private string _PersonID;

private int _Category;

private string _PersonName;

private string _PassWord;

private System.DateTime _RegisterDate;

#region Extensibility Method Definitions
partial void OnLoaded();
partial void OnValidate(System.Data.Linq.ChangeAction action);
partial void OnCreated();
partial void OnPersonIDChanging(string value);
partial void OnPersonIDChanged();
partial void OnCategoryChanging(int value);
partial void OnCategoryChanged();
partial void OnPersonNameChanging(string value);
partial void OnPersonNameChanged();
partial void OnPassWordChanging(string value);
partial void OnPassWordChanged();
partial void OnRegisterDateChanging(System.DateTime value);
partial void OnRegisterDateChanged();
#endregion

public Person()
{
OnCreated();
}

[Column(Storage="_PersonID", DbType="NChar(10) NOT NULL", CanBeNull=false, IsPrimaryKey=true)]
public string PersonID
{
get
{
return this._PersonID;
}
set
{
if ((this._PersonID != value))
{
this.OnPersonIDChanging(value);
this.SendPropertyChanging();
this._PersonID = value;
this.SendPropertyChanged("PersonID");
this.OnPersonIDChanged();
}
}
}

[Column(Storage="_Category", DbType="Int NOT NULL")]
public int Category
{
get
{
return this._Category;
}
set
{
if ((this._Category != value))
{
this.OnCategoryChanging(value);
this.SendPropertyChanging();
this._Category = value;
this.SendPropertyChanged("Category");
this.OnCategoryChanged();
}
}
}

[Column(Storage="_PersonName", DbType="NVarChar(8) NOT NULL", CanBeNull=false)]
public string PersonName
{
get
{
return this._PersonName;
}
set
{
if ((this._PersonName != value))
{
this.OnPersonNameChanging(value);
this.SendPropertyChanging();
this._PersonName = value;
this.SendPropertyChanged("PersonName");
this.OnPersonNameChanged();
}
}
}

[Column(Storage="_PassWord", DbType="NChar(16)")]
public string PassWord
{
get
{
return this._PassWord;
}
set
{
if ((this._PassWord != value))
{
this.OnPassWordChanging(value);
this.SendPropertyChanging();
this._PassWord = value;
this.SendPropertyChanged("PassWord");
this.OnPassWordChanged();
}
}
}

[Column(Storage="_RegisterDate", DbType="DateTime NOT NULL")]
public System.DateTime RegisterDate
{
get
{
return this._RegisterDate;
}
set
{
if ((this._RegisterDate != value))
{
this.OnRegisterDateChanging(value);
this.SendPropertyChanging();
this._RegisterDate = value;
this.SendPropertyChanged("RegisterDate");
this.OnRegisterDateChanged();
}
}
}

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));
}
}
}
}
#pragma warning restore 1591

无法将该类继承别的类,就算你手动修改继承了。当你点到重建Person.DBML后所做的修改全部恢复了。也没有在将类中增加方法,属性。这样很大程度上限制了LINQ的灵活性。请问有什么办法可以解决?
...全文
237 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
如果你在Member数据库表中将Person数据库表已经有的字段(除了主外键以外)又重复了一遍,那么这本身就不是面向对象得了,自然会不知所措。实际上,子类对象在数据库中的表仅应该涉及子类对父类扩展了的那些字段的值,这样把ORM的结构表达最准确(在表达概念时冗余字段有害)。
  • 打赏
  • 举报
回复
我主要是针对“属性方法中自定义业务逻辑代码”而言的,因为这部分是代码生成器自动产生和总是自动覆盖的,所以你只能在产生实体类之后再“注入”业务。你似乎是在考虑比我说的要“浅”的一个问题,就是结构上继承问题。而结构上Linq to SQL的实体类可以表达继承。

在结构上,大多数人的SQL Server表设计不是OO的,这就造成应用程序中的问题。假设说Person的Name是主键,那么叫做“老王”的Member其实“就是”那个叫做“老王”的Person,它们应该是同一个对象,而不应该被表达成两个独立的SQL Server记录。因此,Member数据库表仅应该设计为Person在Member上的扩展字段(仅有一个Name字段作为外键与Person关联)。

把扩展表严格地按照对象类型扩展来设计,才能在应用程序中正确表达继承。linq to SQL的实体类是partial的,因此你要去表达它的父类,无需去手动修改自动产生的实体类代码。
yuling_xia 2008-04-19
  • 打赏
  • 举报
回复
谢谢您!现在可以结贴了!
yuling_xia 2008-04-18
  • 打赏
  • 举报
回复
上面我贴出的代码是一个Person类
假如我还有一个Member类和一个AdminPerson类,这个两个类按照原意是应该继承自Person类的。
因为每个类就是一个数据表,也就是一个LINQ TO SQL的实体类。
既然LINQ TO SQL不允许手动修改而达到继承的目的,那是否需要另外创建新的类如:UMember来包含:Person和Member,和UAdminPerson来包含:Person和AdminPerson呢?
然后在新类:UMember和UAdminPerson中添加相应的业务逻辑?这样做是否是合适的做法?
如果按照您上面的说法“应该通过为它“注入”事件代码这种方式来扩展”那我的这种做法应该是不合理的对吗?
  • 打赏
  • 举报
回复
其实微软“抄袭”什么并不重要,在版权(甚至软件专利)那么泛滥的美国,我们对“抄袭”的描述其实往往没有人家更过分,所以不用太担心一个微软发布的核心技术是否违背“道德”。

实际上,微软发布的这个东西至少比(怀疑)被抄袭的东西要稳定可靠,而且有更好的技术支持和前景,这就够了。
  • 打赏
  • 举报
回复
是的,用别人的工具当然就得接受别人的理念。每一种工具都不太一样。

你贴出的代码已经可以看出,它实现了 INotifyPropertyChanging, INotifyPropertyChanged 两个接口,那么你就可以使用:

TypeDescriptor.GetProperties(o).Find(pname,false).AddValueChanged(o,new EventHandler(proc));

方法来注册回调你的业务逻辑,注册之后它的pname属性的修改就可以执行你的proc。所有业务逻辑都是以属性修改触发自定义事件代码来执行的。

如果你只是要简单地扩展一个对象的代码,特别是在获得一个对象之后去扩展它(你并不拥有它的源代码),不需要为它去定义一个新的父类(这几乎是过于笨重地强调OO和不现实的),而应该通过为它“注入”事件代码这种方式来扩展。
yuling_xia 2008-04-18
  • 打赏
  • 举报
回复
在使用LINQ TO SQL之前我一直用GROVE,在GROVE里可以加入自己的业务逻辑!
我一直都有种感觉,LINQ好像有抄袭GROVE的嫌疑.
yuling_xia 2008-04-18
  • 打赏
  • 举报
回复
感谢楼上大哥的回答!
我好像有一点点理解您的意思了!但我不敢确定理解是否正确!
是不是LINQ TO SQL产生的类只用来做单纯的数据层?只用来新增/删除/修改/查询数据的功能?
其他的业务逻辑全部放到中间层?
比如新增/修改/删除的时候先通过业务逻辑层处理完所有的规则然后返回一个LINQ TO SQL的实体类.再使用LINQ来执行新增/修改/删除的功能呢?
如果是这样的话那就是要自已把LINQ TO SQL 再封装一层?
不知道我的理解是否正确!
  • 打赏
  • 举报
回复
如果你需要嵌入业务逻辑,不应该在对象的表面去完成。我没有使用过Linq to SQL,不过按理来说,你应该在数据源的“回调”中完成业务逻辑。如果Linq to SQL确实没有回调api,并且你又是依赖Linq to SQL来组织程序,那么只能在SQL Server的触发器中执行业务逻辑。SQL Server中似乎从2005版以后就可以使用c#来编写存储过程、触发器,以及server brocker等程序了吧?!即使不会使用c#,使用传统的 t-sql 语言也是一样。

在数据对象的表层不要加入业务逻辑。例如:

class 业务对象类
{
A Property1{get; set;}
B Property2{get; set;}
......
}

这里每一个property set方法最多只应该访问数据库来判断value是否合法,而所有触发业务逻辑应该放在数据源的底层的回调机制中解决。

如果你打算让数据对象去继承很特别的类型,做特别功能的扩展,那么就放弃这种想法。如果你很喜欢让数据存储具有自己的强大的能力,那么你不应该使用Linq to SQL,而应该开发自己的Linq provider来完成那些特别功能,然后再你的Linq provier内部再与SQL Server数据库同步数据。
  • 打赏
  • 举报
回复
[Quote=引用楼主 yuling_xia 的帖子:]
这样很大程度上限制了LINQ的灵活性。请问有什么办法可以解决?
[/Quote]

这样其实是Linq限制了“你的”灵活性,换句话说你的灵活性没有体现出来。

你的类型应该在其中使用Linq,而不是给Linq当父类。

8,497

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 LINQ
社区管理员
  • LINQ
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧