这是程序自动创建的分类。
FCKEditor与ASP.NET集成后,本地测试正常,服务器上运行时在传图片的时候会提示关于权限的js错误。

估计应该跟浏览器权限设置有关系,没有深究,以下是网上的解决方案:

到Fckeditor官方网站下载FredCK.FCKeditorV2.vs2005 (asp.net)

打开解决方案,

找到 FileBrowser/FileWorkerBase.cs 文件


Response.Write( @"(function(){var d=document.domain;while (true){try{var A=window.top.opener.document.domain;break;}catch(e) {};d=d.replace(/.*?(?:\.|$)/,'');if (d.length==0) break;try{document.domain=d;}catch (e){break;}}})();" );

修改成:


Response.Write(@"(function(){var d=document.domain;while (true){try{var A=window.top.opener.document.domain;break;}catch(e) {};d=d.replace(/.*?(?:\.|$)/,'');if (d.length==0) break;}})();");

编译,将DLL文件拷贝覆盖你网站BIN目录的文件



另:FCKEditor除了新的版本,更名为CKEditor,有时间研究下。。。

.NET3.5 与 .NET2.0 的 CLR 是相同的。
从IIS上更容易看得出来,IIS的ASP.NET配置里没有3.5的选项。

所以3.5的程序运行在2.0的空间上是完全没有问题的,只需要解决几个Assembly引用即可。

在安装.NET3.5的本地计算机上到C:\WINDOWS\assembly\GAC_MSIL下各个对应的目录里找到:
System.Core.dll
System.Core.Resources.dll
System.Data.DataSetExtensions.dll
System.Data.DataSetExtensions.Resources.dll
System.Web.Extensions.dll
System.Web.Extensions.Resources.dll
System.Xml.Linq.dll
System.Xml.Linq.Resources.dll

然后复制到网站发布后的bin目录里,就OK了。

要注意的是C:\WINDOWS\assembly\GAC_MSIL这个目录是普通方式是打不开的。
我是通过一个叫Everything的文件搜索工具进去的,你也可以从命令行进入找到所需的文件。

当然,怕麻烦的话,从这下载吧。呵呵:



另外,.NET2.0的空间不支持.NET3.5页面的动态编译(那是肯定的)。所以在发布的时候,请将“允许更新此预编译站点”勾掉,服务器端运行时会出现编译错误。

Tags: , , , , ,
前段时间写了那篇关于Db4o 主键问题的文章,应用时发现Guid类型的主键在数据删除后仍然留在数据文件中。

分析发现Guid类型属于引用类型,Db4o将其当成实体对象保存了,然而在逻辑意义上我们并不认为Guid是以个实体数据。

解决方法自然是有的,Db4o未删除Guid类型的ID,是因为未设置级联删除,在数据库开启前(必须是开启前设置)为类别设置级联删除即可,计提方式请参考相应文档。

但是,Db4o在级联操作上的局限性就在于,只能对一个类别设置级联属性,而不能对单个属性设置(至少我现在没有发现相应的方法可以为单个属性设置级联属性)。这样的话仅仅为了一个ID就对该类设置级联删除是很不明智的,简单考虑一下文章与文章类别的例子就很容易发现了,我要删除文章的ID,就不得不删除文章所属的分类。。。

不用级联删除还可以通过Db4o的事件特性来实现,具体点就是在数据的删除事件中删除他的ID。但是Guid值作为一个逻辑值类型,在数据库中是不止一份的(这个很难讲的明白,就像1 2 3 4这样的值类型,实际上Db4o在存储操作时,完全是把引用类型当值类型用的),当你删除的时候你实际上删除的不是某一个ID,而是数据库中所有的这个Guid。相当于关系型数据库中,我删除了父表中的一项,却没把子表中的引用项设空一样。破坏了数据完整性。

所以最终解决方案是使用一个值类型的id(自动生成可以用Date.Now的滴答数来代替),这就不存在实体类被删除,ID还存在的情况。

同样通过这一现象,我发现Db4o里面使用引用类型的字段是很不安全的,很容易造成数据库垃圾堆积(有点像C里面的内存泄露)。举个例子Subject为文章类型,Article为文章,很自然的我们会如下定义这两个类(.NET3.5):

class Article{
   public string Title{get;set;}
   public Subject Subject;
}

class Subject{
    public string Name;
}

模拟一个基本流程:添加分类->添加文章->修改文章分类->删除文章

首先添加分类会在数据库中创建一条关于分类的记录

添加文章中的Subject属性在保存前会设定一个数据库中存在的分类,但是此处在保存文章时,又会产生一个相同的分类条目(感觉Db4o的Store方法设计有问题)

修改文章分类的时候文章原来的分类是一个被复制的分类,再设置的时候又会有一条分类被复制,甚至于你仅仅修改文章的标题都会有一条分类条目被复制。

不知道Db4o里面对这些“孤岛数据”有没有垃圾回收机制,数据库毕竟与面向对象环境不同,如果这些“孤岛数据”一直存在的话,数据库的急速增长是不可避免的(网上对此问题的抱怨也是有的)。


Db4o的思想很先进,确实给开发工作带来很大便利,可能在实现上还有一定问题,技术尚不成熟(虽然版本已经达到7.X了),所以建议在使用Db4o技术建模时,尽量避免引用类型的使用(string类型除外),特别是一对多关系,尽量用ID代替实际引用。如果不可避免的要用引用类型,要么设置级联删除,要么设置删除事件,要么就干脆使用“特性标记”使该字段不可被序列化


Db4o真的没想象中那么简单。

关于Db4o的使用,后续还会有文章介绍

静态构造函数总是至多被调用一次吗?静态构造函数一定会被调用吗?看如下反例:

namespace ConsoleApplication1
{
    class Program:A<float>
    {
        static Program()
        {
            Console.WriteLine("Class Program static construct invoked.");
        }

        static void Main(string[] args)
        {
            Console.WriteLine(B.SomeValue++);
            Console.WriteLine(C.SomeValue++);
            Console.WriteLine(D.SomeValue++);
            Console.WriteLine(E.SomeValue++);
            Console.WriteLine(E.SomeValue2++);

            new F();
            new F();

            Console.ReadKey();

        }
    }

    class A<T>
    {
        public static int SomeValue=0;

        public A()
        {
            Console.WriteLine("Class A<{0}> dynamic construct invoked.", typeof(T).Name);
        }


        static A()
        {
            Console.WriteLine("Class A<{0}> static construct invoked.",typeof(T).Name);
        }
    }

    class B : A<string>
    {
        static B()
        {
            Console.WriteLine("Class B static construct invoked.");
        }
    }


    class C : A<int>
    {
        static C()
        {
            Console.WriteLine("Class C static construct invoked.");
        }
    }

    class D : A<int>
    {
        static D()
        {
            Console.WriteLine("Class D static construct invoked.");
        }
    }

    class E : A<float>
    {
        public static int SomeValue2 = 0;
        static E()
        {
            Console.WriteLine("Class E static construct invoked.");
        }
    }

    class F : A<bool>
    {
        public F()
        {
            Console.WriteLine("Class F dynamic construct invoked.");
        }

        static F()
        {
            Console.WriteLine("Class F static construct invoked.");
        }
    }

}


输出如下:
Class Programe static construct invoked.
Class A<String> static construct invoked.
0
Class A<Int32> static construct invoked.
0
1
Class A<Single> static construct invoked.
0
Class E static construct invoked.
0
Class F static construct invoked.
Class A<Boolean> static construct invoked.
Class A<Boolean> dynamic construct invoked.
Class F dynamic construct invoked.
Class A<Boolean> dynamic construct invoked.
Class F dynamic construct invoked.

对输出结果分析如下:

//程序运行实际上是Framework调用Program的Main静态方法,但不会实例化Program
Class Program static construct invoked.  
//实际上静态成员并不支持继承,C#编译器会在底层将B.SomeValue翻译成A<string>.SomeValue
//所以被加载的不是B,而是A<string>
Class A<String> static construct invoked. 
0
//同样此处C.SomeValue被翻译成A<int>.SomeValue
Class A<Int32> static construct invoked.
//诧异?被继承的SomeValue不是被“加加”了吗,为何此处还是0
0
//看到了吧,SomeValue确实被“加加”了,不过A<string>与A<int>属于不同的类型
//里面的SomeValue也是相互独立的
1
//E.SomeValue被翻译成A<float>.SomeValue
Class A<Single> static construct invoked.
0
//此处的E.SomeValue2远远本本的就是E.SomeValue2当然E的静态构造函数会被执行。
//现在我们才发觉B/C/D三者的静态构造函数都没被执行,原因呢,刚才也说了,实际上
//上面的B/C/D的引用在底层都被翻译成了A的封闭类,所以加载的并不是B/C/D本身,而是
//相应的封闭类
Class E static construct invoked.
0
//现在再来温习一下静态构造方法与构造方法的执行顺序
//因为new的是F,所以F首先被加载,进而执行F的静态构造
Class F static construct invoked.
//加载F后发现F是从A<bool>继承的,进而去加载A<bool>,于是A<bool>的静态构造被执行
Class A<Boolean> static construct invoked.
//首先执行基类的构造方法
Class A<Boolean> dynamic construct invoked.
//而后是F自己的构造方法
Class F dynamic construct invoked.
//此两句因为A<bool>与F以被加载,静态构造已被执行,因而直接按顺序从低往高调用构造方法
Class A<Boolean> dynamic construct invoked.
Class F dynamic construct invoked.


总结:
1.泛型类的各封闭类,属于不同的类,各自有自己独立的静态空间
2.静态成员实际上不支持继承,C#编译器在底层将实际的引用确定成静态成员定义者
3.静态构造函数不一定会被执行,因为有的类,在执行过程中不会被加载
4.静态构造函数确实是总是至多被调用一次,但是泛型类的静态构造要站在另一个角度考虑
5.类的构造函数执行顺序是自底而上
6.类的静态构造函数执行顺序是不能确定的,因为编程过程中,类的使用顺序是不定的,静态构造函数总是在类第一次被用到的地方执行

看了诸多关于ID问题的讨论后,决定用Guid结合插入时事件来实现ID唯一性。

实现如下(.NET3.5的自动属性):

//实体基类
public abstract class Entity{
    public Guid ID{
        get;set;
    }
}

//汽车
public class Car:Entity{
    public Person Owner{
        get;set;
    }
}

//人
//public class Person:Entity{
    public string Name{
        get;set;
    }
}



以下是业务基类:
    public abstract class BLLBase<T> : ICommonBLL<T> where T : Entity
    {
        //静态ObjectServer对象用以持有数据文件

        protected static IObjectServer DBS;

        //静态ObjectContainer对象,用于静态代码中的数据操作
        protected static IObjectContainer DBC;

        //DB4O的事件注册器
        protected static IEventRegistry DBER;

        //运行时的ObjectContainer实例

        protected IObjectContainer DB;

        /// <summary>
        /// 静态构造用于打开ObjectServer及注册应用程序结束事件
        /// </summary>
        static BLLBase()
        {
            //BLLFactoryBase在BLLBase加载前要准备好ConnectionString
            //此处在实际Factory被加载时会初始化ObjectServer
            IConfiguration conf = Db4oFactory.NewConfiguration();
            conf.BlockSize(8);
            conf.ActivationDepth(2);

            //初始化静态ObjectServer/ObjectClient及事件注册器
            DBS = Db4oFactory.OpenServer(conf, Factory.ConnectionString, 0);
            DBC = DBS.OpenClient();
            DBER = EventRegistryFactory.ForObjectContainer(DBC);

            DBER.Creating += new CancellableObjectEventHandler(BLLBase_Creating);

            //进程结束时关闭ObjectServer
            AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);
        }

        /// <summary>
        /// 应用程序结束事件,用于关闭ObjectServer
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        static void CurrentDomain_ProcessExit(object sender, EventArgs args)
        {
            DBC.Close();
            DBS.Close();
        }

        /// <summary>
        /// 数据创建事件,自动生成唯一性标识
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        static void BLLBase_Creating(object sender, ObjectEventArgs args)
        {
            Model.Entity ent = args.Object as Entity;
            if (ent != null)
                ent.ID = Guid.NewGuid();

        }

        /// <summary>
        /// 构造时打开连接
        /// </summary>
        public BLLBase()
        {
            DB = DBS.OpenClient();
        }

        /// <summary>
        /// 不用时释放连接
        /// </summary>
        ~BLLBase()
        {
            DB.Close();
        }

        //增删改查的基础实现省略
    }

在进行插入操作时会引发BLLBase_Creating,会给实体对象的ID赋一个唯一的值。



但是在实际调试中插入后其他属性都有值,就是ID没有,但调试过程中确实看到Guid.NewGuid()的运行并被赋给ID。但却保存不了,近两个小时的折腾之后,却发现是.NET3.5自动属性搞的鬼。

原来DB4O保存的是对当前对象可见的域,而自动属性被编译器翻译后最终会成为如下形式:

public class Entity{
    private Guid _ID;
    public Guid ID{
        get{return _ID;}
        set{_ID=value;}
    }
}

显然无论是Car还是Person从Entity继承来的_ID对他们来说都是不可见的,所以不会被保存。

明白以后就修改Entity的各个属性将私有域改为protected即可

分页: 1/4 第一页 1 2 3 4 下页 最后页 [ 显示模式: 摘要 | 列表 ]