Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用于自身数据访问的惰性运算符C#_C#_Winforms_Entity Framework_Orm - Fatal编程技术网

用于自身数据访问的惰性运算符C#

用于自身数据访问的惰性运算符C#,c#,winforms,entity-framework,orm,C#,Winforms,Entity Framework,Orm,我目前正在winforms中构建一个医疗计划类型的应用程序。我已经实现了数据访问的延迟加载方法。我不能使用像EF或nHibernate这样的ORM,所以我用自己的逻辑实现了它。我在一个类上有多个字段,例如包,其中包含导航属性,例如List,它应该包含此包的所有处理。用lazy包装整个列表是一种不好的做法,它会被实例化如下: Package package = new Package() { PackageID = record.GetInt

我目前正在winforms中构建一个医疗计划类型的应用程序。我已经实现了数据访问的延迟加载方法。我不能使用像EF或nHibernate这样的ORM,所以我用自己的逻辑实现了它。我在一个类上有多个字段,例如包,其中包含导航属性,例如
List
,它应该包含此包的所有处理。用lazy包装整个列表是一种不好的做法,它会被实例化如下:

        Package package = new Package()
        {
            PackageID = record.GetInt32(0),
            Name = record.GetString(1),
            CoverageAmount = record.GetDecimal(2),
            PackageStatus = (Status)record.GetInt32(3),
            AvaliableFrom = record.GetDateTime(4),
            AvaliableTo = record.GetDateTime(5),
        };

        package.Policies = new Lazy<List<Policy>>(() =>
        {
            return GetPoliciesByPackageID(package.PackageID);
        });

        package.Treatments = new Lazy<List<Treatment>>(() =>
        {
            return GetTreatmentsByPackage(package.PackageID);
        });

        return package; 
Package-Package=new-Package()
{
PackageID=record.GetInt32(0),
Name=record.GetString(1),
CoverageAmount=record.GetDecimal(2),
PackageStatus=(状态)记录。GetInt32(3),
AvailableFrom=record.GetDateTime(4),
AvaliableTo=record.GetDateTime(5),
};
package.Policies=newlazy(()=>
{
返回GetPoliciesByPackageID(package.PackageID);
});
package.Treatments=newlazy(()=>
{
return GetTreatmentsByPackage(package.PackageID);
});
退货包装;

当我需要所有的治疗时,我不得不称之为package.treatments.Value,这感觉有点不对劲。不赞成这种方法。

延迟实例化本身并不是一种坏做法,但是,如果您通过属性公开昂贵的(就获取结果所花费的时间而言)值,那么这是一种坏做法。属性旨在快速访问对象部分状态的曝光。如果您以昂贵的成本获取数据,那么就公开一个方法。

数据延迟加载的事实似乎是一个实现细节。因此,我将封装它

public class Package
{
    private readonly Lazy<List<Policy>> _lazyPolicies =  ...

    public List<Policy> Policies
    {
        get { return _lazyPolicies.Value; }
    }
}
公共类包
{
私有只读懒策略=。。。
公开名单政策
{
获取{return\u lazyPolicies.Value;}
}
}
如果您想模仿NHibernate的做法,可以使用

下面是一个简单的(线程不安全的)代理:

公共接口IPackage
{
列出策略{get;}
}
公共类包
{
公共列表策略{get;set;}
}
公共类PackageProxy
{
私有只读包_包;
私有只读数据库_db;
公共包代理(包、数据库_db)
{
_包装=包装;
_db=db;
}
公开名单政策
{
得到
{
如果(_package.Policies==null)
_package.Policies=GetPoliciesByPackageID(package.PackageID);
退货包装政策;
}
}
私有列表GetPoliciesByPackageID(int id)
{
_数据库。。。
}
}
//用法
IPackage package=new PackageProxy(new package(),db){/**set properties**/};

我喜欢这种方法,这是我看到的唯一问题。据我所知,readonly允许在构造函数内赋值。我不使用它,因为这些对象纯粹是包含许多字段和属性的数据。构造器将相当长,出于个人喜好,我不知道like@RiaanvanRooyen好吧,如果他们的数据将被延迟加载,那么他们就不会像你最初认为的那样“愚蠢”。另一种选择是通过代理(或动态代理)执行此操作,与NHibernate执行此操作的方式相同。DTO将具有“哑”属性,代理将环绕DTO,公开相同的接口,但在调用属性getter时调用数据库。谢谢。我还在学习,目前正在南非学习软件工程。我非常感谢您的建议,我将明确研究动态代理。您是否有任何资源显示Entity Framework或NHibernate的内部信息?@RiaanvanRooyen我没有,我读过他们使用的技术,但我不记得在哪里。不过应该很容易找到。此外,NHibernate还用于在运行时动态生成对象的代理。我添加了一个非动态手动编写的代理的示例,以演示幕后发生的事情。谢谢,这是非常好的布局。这是一个好主意。非常感谢我会投票,但没有足够的声誉。第一个问题当前使用的方法是
GetTreatmentsByPackage
,这样就可以调用查询数据库的存储库。所以这可能是相当“昂贵”的。那么懒惰行为是你想要的吗?惰性内部实例在计算后将永远不会更改,因此,如果数据库发生更改,您将继续从惰性内部实例返回陈旧数据。因此,惰性内部实例的内部将只计算一次{return GetTreatmentsByPackage(package.PackageID);}。那么在重复通话时,它会做什么?数据存储在什么地方吗?我想我有不同的理解,可能是错的。是的,它只被评估一次(警告:不是线程安全的-请参阅AsyncLazy)。所以,一旦它被评估,它就会存储结果,并在每次查询值时返回结果。谢谢,伙计,我不知道这一点。我会调查的。看来我的设计不像我想象的那么坚如磐石。有两个对象使用相同的逻辑。
public interface IPackage
{
    List<Policy> Policies { get; }
}

public class Package
{
    public List<Policy> Policies { get ; set; }
}

public class PackageProxy
{
    private readonly Package _package;
    private readonly Database _db;

    public PackageProxy(Package package, Database _db)
    {
        _package = package;
        _db = db;
    }

    public List<Policy> Policies
    {
        get
        {
            if(_package.Policies == null)
                _package.Policies = GetPoliciesByPackageID(package.PackageID);
            return _package.Policies;
        }
    }

    private List<Policy> GetPoliciesByPackageID(int id)
    {
        _db...
    }
}

// usage

IPackage package = new PackageProxy(new Package(), db) { /** set properties **/ };