65.9K
CodeProject 正在变化。 阅读更多。
Home

LINQ FAQ: 第 2 部分

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.93/5 (13投票s)

2009年7月13日

CPOL

13分钟阅读

viewsIcon

69146

downloadIcon

2279

本 FAQ 文章专门介绍 LINQ to SQL。

目录

引言和目标

本 FAQ 文章专门介绍 LINQ to SQL。在本文中,我们将介绍 LINQ to SQL 的基本示例、如何使用 LINQ 定义一对一和一对多关系、如何优化 LINQ 查询、LINQ 执行存储过程,最后我们将介绍 LINQ to SQL 的一个简单 CRUD 示例。在过去的几天里,我一直在进行一个小冲刺来完成这场马拉松。希望您会喜欢这篇文章。

其他 LINQ FAQ

能否提供一个简单的 LINQ to SQL 示例?

让我们先从一个简单的 LINQ to SQL 示例开始,然后尝试理解如何在 LINQ 实体中建立关系。

步骤 1:使用 LINQ 定义实体类

当我们使用分层方法(如三层或 N 层)设计项目时,我们需要创建业务类和对象。例如,代码定义了一个映射到 Country 表的类。您可以看到类属性如何以一对一的方式映射到表。这些类型的类称为实体类。

在 LINQ 中,我们需要首先使用属性映射来定义这些实体类。您需要导入 System.Data.Linq.Mapping 命名空间来获取映射属性。以下代码片段展示了 Table 属性如何将类映射到数据库表 Customer,以及 Column 属性如何帮助将属性映射到表列。

[Table(Name = "Customer")]
public class clsCustomerEntityWithProperties
{
    private int _CustomerId;
    private string _CustomerCode;
    private string _CustomerName;

    [Column(DbType = "nvarchar(50)")]
    public string CustomerCode
    {
        set
        {
            _CustomerCode = value;
        }
        get
        {
            return _CustomerCode;
        }
    }

    [Column(DbType = "nvarchar(50)")]
    public string CustomerName
    {
        set
        {
            _CustomerName = value;
        }
        get
        {
            return _CustomerName;
        }
    }

    [Column(DbType = "int", IsPrimaryKey = true)]
    public int CustomerId
    {
        set
        {
            _CustomerId = value;
        }
        get
        {
            return _CustomerId;
        }
    }
}

下面是实体类映射到 Customer 表结构的更复杂的图示。

步骤 2:使用 DataContext 将表数据绑定到实体对象

第二步是使用 LINQ 的数据上下文对象来填充您的实体对象。DataContext 在数据库对象和您的 LINQ 实体映射类之间充当中介。

所以要做的第一件事是创建一个 DataContext 对象,并使用 SQL 连接字符串创建一个活动连接。

DataContext objContext = new DataContext(strConnectionString);

接下来要做的是使用 Table 数据类型获取实体集合。这是通过 DataContextGetTable 函数完成的。

Table<clsCustomerEntity> objTable = objContext.GetTable<clsCustomerEntity>();

一旦我们在 Table 集合中获取了所有数据,就是时候浏览 Table 集合并显示记录了。

foreach (clsCustomerEntity objCustomer in objTable)
{
    Response.Write(objCustomer.CustomerName + "<br>");
}

您可以通过本文附带的源代码获取上述代码。

我们能否为 LINQ 实体封装 get 和 set 属性?

在上一个问题中,我们暴露了实体类的属性为公共属性,这违反了封装的基本规则。您可以定义 setter 和 getter 函数来封装私有属性。

[Table(Name = "Customer")]
public class clsCustomerEntityWithProperties
{
    private int _CustomerId;
    private string _CustomerCode;
    private string _CustomerName;

    [Column(DbType = "nvarchar(50)")]
    public string CustomerCode
    {
        set
        {
            _CustomerCode = value;
        }
        get
        {
            return _CustomerCode;
        }
    }

    [Column(DbType = "nvarchar(50)")]
    public string CustomerName
    {
        set
        {
            _CustomerName = value;
        }
        get
        {
            return _CustomerName;
        }
    }

    [Column(DbType = "int", IsPrimaryKey = true)]
    public int CustomerId
    {
        set
        {
            _CustomerId = value;
        }
        get
        {
            return _CustomerId;
        }
    }
}

能否提供一对一和一对多关系的简单示例?

LINQ 使用 EntitySetEntityRef 来帮助您定义关系。为了理解如何使用 LINQ 定义关系,让我们考虑下面的示例,其中一个客户可以拥有多个地址,而每个地址都有电话详细信息。换句话说,客户和地址之间存在一对多关系,而地址和电话之间存在一对一关系。

要定义客户和地址类之间的一对多关系,我们需要使用 EntitySet 属性。要定义地址类和电话类之间的一对一关系,我们需要使用 EntityRef 属性。

注意:您需要为每个实体类定义主键属性,否则映射关系将不起作用。

下面是客户类的类实体代码片段,展示了它如何使用 EntitySet 来定义与地址类的一对多关系。关联是使用 Association 属性定义的。Association 属性有三个重要属性:storagethiskeyotherkeystorage 定义了存储地址对象的私有变量的名称;目前是 _CustomerAddressesThisKeyOtherKey 定义了哪些属性将定义链接;在此实例中,它是 CustomerId。换句话说,客户类和地址类都将具有共同的 CustomerId 属性。ThisKey 定义了客户类的属性名称,而 OtherKey 定义了地址类的属性。

[Table(Name = "Customer")]
public class clsCustomerWithAddresses
{
    private EntitySet<clsAddresses> _CustomerAddresses;

    [Association(Storage = "_CustomerAddresses",
      ThisKey="CustomerId", OtherKey = "CustomerId")]
    public EntitySet<clsAddresses> Addresses
    {
        set
        {
            _CustomerAddresses = value;
        }
        get
        {
            return _CustomerAddresses;
        }
    }
}

下面是包含客户类其他属性的完整代码片段

[Table(Name = "Customer")]
public class clsCustomerWithAddresses
{
    private int _CustomerId;
    private string _CustomerCode;
    private string _CustomerName;
    private EntitySet<clsAddresses> _CustomerAddresses;

    [Column(DbType="int",IsPrimaryKey=true)]
    public int CustomerId
    {
        set
        {
            _CustomerId = value;
        }
        get
        {
            return _CustomerId;
        }
    }

    [Column(DbType = "nvarchar(50)")]
    public string CustomerCode
    {
        set
        {
            _CustomerCode = value;
        }
        get
        {
            return _CustomerCode;
        }
    }

    [Column(DbType = "nvarchar(50)")]
    public string CustomerName
    {
        set
        {
            _CustomerName = value;
        }
        get
        {
            return _CustomerName;
        }
    }

    [Association(Storage = "_CustomerAddresses",ThisKey="CustomerId", OtherKey = "CustomerId")]
    public EntitySet<clsAddresses> Addresses
    {
    set
        {
            _CustomerAddresses = value;
        }
        get
        {
            return _CustomerAddresses;
        }
    }
}

要定义地址类和电话类之间的关系,我们需要使用 EntityRef 语法。下面是使用 EntityRef 定义关系的的代码片段。所有其他属性都相同,只是我们需要使用 EntityRef 定义变量。

public class clsAddresses
{
    private int _AddressId;
    private EntityRef<clsPhone> _Phone;

    [Column(DbType = "int", IsPrimaryKey = true)]
    public int AddressId
    {
        set
        {
            _AddressId = value;
        }
        get
        {
            return _AddressId;
        }
    }
    [Association(Storage = "_Phone", 
    ThisKey = "AddressId", OtherKey = "AddressId")]
    public clsPhone Phone
    {
        set
        {
            _Phone.Entity = value;
        }
        get
        {
            return _Phone.Entity;
        }
    }
}

下面是包含其他属性的完整地址类

public class clsAddresses
{
    private int _Customerid;
    private int _AddressId;
    private string _Address1;
    private EntityRef<clsPhone> _Phone;
    [Column(DbType="int")]
    public int CustomerId
    {
        set
        {
            _Customerid = value;
        }
        get
        {
            return _Customerid;
        }
    }
    [Column(DbType = "int", IsPrimaryKey = true)]
    public int AddressId
    {
        set
        {
            _AddressId = value;
        }
        get
        {
            return _AddressId;
        }
    }
    [Column(DbType = "nvarchar(50)")]
    public string Address1
    {
        set
        {
            _Address1 = value;
        }
        get
        {
            return _Address1;
        }
    }
    [Association(Storage = "_Phone", 
    ThisKey = "AddressId", OtherKey = "AddressId")]
    public clsPhone Phone
    {
        set
        {
            _Phone.Entity = value;
        }
        get
        {
            return _Phone.Entity;
        }
    }
}

这是与地址类聚合的电话类

[Table(Name = "Phone")]
public class clsPhone
{
    private int _PhoneId;
    private int _AddressId;
    private string _MobilePhone;
    private string _LandLine;

    [Column(DbType = "int", IsPrimaryKey = true)]
    public int PhoneId
    {
        set
        {
            _PhoneId = value;
        }
        get
        {
            return _PhoneId;
        }
    }
    [Column(DbType = "int")]
    public int AddressId
    {
        set
        {
            _PhoneId = value;
        }
        get
        {
            return _PhoneId;
        }
    }
    [Column(DbType = "nvarchar")]
    public string MobilePhone
    {
        set
        {
            _MobilePhone = value;
        }
        get
        {
            return _MobilePhone;
        }
    }
    [Column(DbType = "nvarchar")]
    public string LandLine
    {
        set
        {
            _LandLine = value;
        }
        get
        {
            return _LandLine;
        }
    }
}

现在,我们最终需要在 ASPX 客户端后台代码中消费这种关系。

第一步是创建初始化连接的 DataContext 对象。

DataContext objContext = new DataContext(strConnectionString);

第二步是触发查询。请注意,我们只是为客户类触发查询。LINQ 引擎确保所有子表数据都根据实体类中定义的关联进行提取和放置。

var MyQuery = from objCustomer in objContext.GetTable<clsCustomerWithAddresses>()
select objCustomer;

最后,我们遍历客户,遍历相应的地址对象,并根据电话对象显示电话详细信息。

foreach (clsCustomerWithAddresses objCustomer in MyQuery)
{
    Response.Write(objCustomer.CustomerName + "<br>");
    foreach (clsAddresses objAddress in objCustomer.Addresses)
    {
        Response.Write("===Address:- " + objAddress.Address1 + "<br>");
        Response.Write("========Mobile:- " + objAddress.Phone.MobilePhone + "<br>");
        Response.Write("========LandLine:- " + objAddress.Phone.LandLine + "<br>");
    }
}

输出看起来如下所示。每个客户有多个地址,每个地址都有一个电话对象。

能否解释一下 LINQ 中的往返旅行是如何发生的?

首先,让我们尝试理解 LINQ 查询是如何工作的,然后我们将看到往返旅行是如何发生的。让我们考虑下面三个表:customer、addresses 和 phone 的数据库设计。customer 和 addresses 之间有一对多关系,而 address 和 phones 之间有一对一关系。

我们根据表设计创建了三个实体:ClsCustomerWithAddressesClsAddressesClsPhone。我们使用 EntitySetEntityRef 在它们之间定义了关系。

使用表数据填充实体对象是一个五步过程。作为第一步,使用连接字符串创建 DataContext 连接,创建 LINQ 查询,然后我们开始浏览客户、地址和电话。

分析 LINQ SQL 往返旅行

好的,既然我们已经分析了执行 LINQ 查询需要五个步骤,那么让我们尝试找出 LINQ 查询实际向数据库发出 SQL 的步骤。我们将运行上述 LINQ 代码,并使用 SQL Profiler 进行分析。

为了避免被大量的 SQL Server 噪音干扰,我们只启用了 RPC 和 SQL 批处理事件。

现在,当您运行查询时,您会发现以下内容

  • 实际 SQL 的执行发生在 foreach 语句遍历 LINQ 对象时。
  • 您会注意到的第二个非常惊人的事情是,对于每个实体,都会向 SQL Server 发出一个单独的查询。例如,对于客户,会发出一个查询,然后会单独为地址和电话发出查询来丰富实体对象。换句话说,大量的往返旅行。

我们如何避免额外的往返旅行?

我们可以指示 LINQ 引擎使用 DataLoadOptions 加载所有对象。以下是启用 DataLoadOptions 所涉及的步骤。

第一步是创建 DataContext

DataContext objContext = new DataContext(strConnectionString);

第二步是创建 DataLoadOption 对象

DataLoadOptions objDataLoadOption = new DataLoadOptions();

使用 LoadWith 方法,我们需要定义我们希望在单个 SQL 中加载客户及其地址。

objDataLoadOption.LoadWith<clsCustomerWithAddresses>(
         clsCustomerWithAddresses => clsCustomerWithAddresses.Addresses);

每个地址对象都有一个电话对象,因此我们也定义了希望在单个 SQL 中为每个地址对象加载电话对象。

objDataLoadOption.LoadWith<clsAddresses>(clsAddresses => clsAddresses.Phone);

无论您定义了什么加载选项,都需要使用 LoadOptions 属性将其设置为 DataContext 对象。

objContext.LoadOptions = objDataLoadOption;

最后,准备您的查询。

var MyQuery = from objCustomer in objContext.GetTable<clsCustomerWithAddresses>()
select objCustomer;

开始遍历对象

foreach (clsCustomerWithAddresses objCustomer in MyQuery)
{
    Response.Write(objCustomer.CustomerName + "<br>");

    foreach (clsAddresses objAddress in objCustomer.Addresses)
    {
        Response.Write("===Address:- " + objAddress.Address1 + "<br>");
        Response.Write("========Mobile:- " + objAddress.Phone.MobilePhone + "<br>");
        Response.Write("========LandLine:- " + objAddress.Phone.LandLine + "<br>");
    }
}

以下是完整的源代码

DataContext objContext = new DataContext(strConnectionString);
DataLoadOptions objDataLoadOption = new DataLoadOptions();
objDataLoadOption.LoadWith<clsCustomerWithAddresses>(
   clsCustomerWithAddresses => clsCustomerWithAddresses.Addresses);
objDataLoadOption.LoadWith<clsAddresses>(clsAddresses => clsAddresses.Phone);
objContext.LoadOptions = objDataLoadOption;
var MyQuery = from objCustomer in objContext.GetTable<clsCustomerWithAddresses>()
select objCustomer;

foreach (clsCustomerWithAddresses objCustomer in MyQuery)
{
    Response.Write(objCustomer.CustomerName + "<br>");

    foreach (clsAddresses objAddress in objCustomer.Addresses)
    {
        Response.Write("===Address:- " + objAddress.Address1 + "<br>");
        Response.Write("========Mobile:- " + objAddress.Phone.MobilePhone + "<br>");
        Response.Write("========LandLine:- " + objAddress.Phone.LandLine + "<br>");
    }
}

咒语生效……现在,如果您运行代码,LINQ 只执行了一个带有正确连接的 SQL,与之前为每个对象显示的三个 SQL 相比。

源代码

此源代码随本文一起提供。运行项目,查看 Profiler 如何显示不同的 SQL 执行。您可以先运行 EntitySet 示例,查看 SQL Profiler 的反应,然后运行带有 DataLoadOptions 的示例。SQL 脚本已单独保存到文件中。

我们如何使用 LINQ 执行存储过程?

步骤 1:创建存储过程

下面是我们用于丰富 LINQ 对象的存储过程

Create PROCEDURE dbo.usp_SelectCustomer
AS
Select CustomerId,CustomerCode,CustomerName from Customer
RETURN

步骤 2:创建 LINQ 实体

上述存储过程返回 CustomerId、CustomerCode 和 CustomerName,因此我们需要根据返回的存储过程数据准备一个 LINQ 实体。如果您不熟悉 LINQ 实体,请参阅 OneManyandOneOneLINQ.aspx 上的基础知识。

[Table(Name = "Customer")]
public class clsCustomerEntity
{
    private int _CustomerId;
    private string _CustomerCode;
    private string _CustomerName;

    [Column(DbType = "nvarchar(50)")]
    public string CustomerCode
    {
        set
        {
            _CustomerCode = value;
        }
        get
        {
            return _CustomerCode;
        }
    }

    [Column(DbType = "nvarchar(50)")]
    public string CustomerName
    {
        set
        {
            _CustomerName = value;
        }
        get
        {
            return _CustomerName;
        }
    }

    [Column(DbType = "int", IsPrimaryKey = true)]
    public int CustomerId
    {
        set
        {
            _CustomerId = value;
        }
        get
        {
            return _CustomerId;
        }
    }
}

步骤 3:继承 DataContext 类

为了执行存储过程,LINQ 提供了 DataContext 类中的 ExecuteMethod 调用函数。此函数返回实体集合的 ISingleresultExecuteMethod 调用函数是一个受保护的函数,只能通过继承调用。我们调用存储过程的方法和函数通常构成我们的 DAL。换句话说,ExecuteMethod 应该是我们 DAL 的一部分。

如前所述,该函数是纯受保护的。您只能通过继承调用它,而不能通过聚合。我真的不确定为什么 Microsoft 会设置这个强制性限制。换句话说,我们需要创建一个额外的类来继承 DataContext,然后在此类中放置相应的存储过程调用函数。下面是继承自 DataContext 类并创建了一个名为 ClsMyContext 的新 DAL 类的代码片段。

public class clsMyContext : DataContext
{}

步骤 4:使用 Function 属性进行属性化

我们创建了 GetCustomerAll 函数,该函数使用 System.Data.Linq.Mapping 命名空间中的 Function 属性进行属性化。Function 属性有一个 name 参数,指定存储过程的名称;目前,存储过程是 usp_SelectCustomer,如前几步所述。

IsComposable 参数定义此方法调用是用于存储过程还是用户定义函数 (UDF)。如果 IsComposablefalse,则表示它是存储过程;如果为 true,则表示它是用户定义函数。

[Function(Name = "usp_SelectCustomer", IsComposable = false)]

public ISingleResult<clsCustomerEntity> getCustomerAll()
{
}

步骤 5:调用 ExecuteMethod 调用

现在是时候填充空函数 GetCustomerAll 了。下面是如何执行 ExecuteMethod 调用。此调用返回一个 IExecuteResult 对象。

IExecuteResult objResult = this.ExecuteMethodCall(this,(MethodInfo)(MethodInfo.GetCurrentMethod()));

IExecuteResult 返回的对象具有 ReturnValue 属性,通过该属性我们可以获取 ClsCustomerEntity 类型的集合结果。

ISingleResult<clsCustomerEntity> objresults = (ISingleResult<clsCustomerEntity>) objResult.ReturnValue;

下面是包含该函数的完整代码片段

[Function(Name = "usp_SelectCustomer", IsComposable = false)]
public ISingleResult<clsCustomerEntity> getCustomerAll()
{
    IExecuteResult objResult = 
      this.ExecuteMethodCall(this,(MethodInfo)(MethodInfo.GetCurrentMethod()));

    ISingleResult<clsCustomerEntity> objresults = 
      (ISingleResult<clsCustomerEntity>) objResult.ReturnValue;
    return objresults;
}

步骤 6:最后我们在客户端调用数据上下文

在最后一步中,我们只需创建上下文对象,调用我们的函数,然后遍历对象集合来显示数据。

clsMyContext objContext = new clsMyContext(strConnectionString);
foreach(var row in objContext.getCustomerAll())
{
    Response.Write(row.CustomerCode);
}

能否解释一下 LINQ 内存提交和物理提交?

实体对象构成了 LINQ 技术的基础。因此,当任何数据提交到数据库时,它都会经过 LINQ 对象。数据库操作通过 DataContext 类进行。如前所述,实体构成了 LINQ 的基础,因此所有数据首先发送到这些实体,然后路由到实际的物理数据库。由于这种工作方式,数据库提交是一个两步过程。第一步是内存中的操作,最后一步是物理提交。为了进行内存操作,DataContext 提供了 DeleteOnSubmitInsertOnSubmit 方法。当我们从 DataContext 类调用这些方法时,它们会在实体对象的内存中添加和更新数据。请注意,这些方法不会更改/添加实际数据库中的新数据。一旦我们完成了内存操作,并且想要将所有更新发送到数据库,我们就需要调用 SubmitChanges() 方法。此方法最终将数据提交到物理数据库。

让我们考虑一个客户表(customerid、customercode 和 customername),看看我们如何进行内存和物理提交操作。

能否提供一个简单的 LINQ CRUD 示例?

步骤 1:创建实体 Customer 类

作为第一步,我们创建了一个 Customer 类实体,如下面的代码片段所示。

[Table(Name = "Customer")]
public class clsCustomerEntity
{
    private int _CustomerId;
    private string _CustomerCode;
    private string _CustomerName;

    [Column(DbType = "nvarchar(50)")]
    public string CustomerCode
    {
        set
        {
            _CustomerCode = value;
        }
        get
        {
            return _CustomerCode;
        }
    }

    [Column(DbType = "nvarchar(50)")]
    public string CustomerName
    {
        set
        {
            _CustomerName = value;
        }
        get
        {
            return _CustomerName;
        }
    }

    [Column(DbType = "int", IsPrimaryKey = true,IsDbGenerated=true)]
    public int CustomerId
    {
        set
        {
            _CustomerId = value;
        }
        get
        {
            return _CustomerId;
        }
    }
}

步骤 2:使用 LINQ 创建

创建数据上下文

第一件事是使用连接字符串创建一个 DataContext 对象。

DataContext objContext = new DataContext(strConnectionString);

设置插入数据

一旦您使用 DataContext 对象创建了连接,下一步就是创建 Customer 实体对象并将数据设置到对象属性。

clsCustomerEntity objCustomerData = new clsCustomerEntity();
objCustomerData.CustomerCode = txtCustomerCode.Text;
objCustomerData.CustomerName = txtCustomerName.Text;

执行内存更新

然后我们使用 InsertOnSubmit 方法在实体对象中进行内存更新。

objContext.GetTable<clsCustomerEntity>().InsertOnSubmit(objCustomerData);

执行最终物理提交

最后,我们执行物理提交到实际数据库。请注意,直到我们调用 SubmitChanges(),数据才会被提交到数据库。

objContext.SubmitChanges();

最终的 Create LINQ 代码

下面是最终整合的 LINQ 代码

DataContext objContext = new DataContext(strConnectionString);
clsCustomerEntity objCustomerData = new clsCustomerEntity();
objCustomerData.CustomerCode = txtCustomerCode.Text;
objCustomerData.CustomerName = txtCustomerName.Text;
objContext.GetTable<clsCustomerEntity>().InsertOnSubmit(objCustomerData);
objContext.SubmitChanges();

步骤 3:使用 LINQ 更新

让我们来看下一个数据库操作,即更新。

创建数据上下文

照常,我们首先需要创建一个 DataContext 对象,使用连接字符串,这在创建步骤中已经讨论过。

DataContext objContext = new DataContext(strConnectionString);

选择要更新的 Customer LINQ 对象

使用要更新的 LINQ 查询获取 LINQ 对象

var MyQuery = from objCustomer in objContext.GetTable<clsCustomerEntity>()
where objCustomer.CustomerId == Convert.ToInt16(txtCustomerId.Text)
select objCustomer;

最后设置新值并更新物理数据库的数据

执行更新并调用 SubmitChanges() 来执行最终更新。

clsCustomerEntity objCustomerData = (clsCustomerEntity)MyQuery.First<clsCustomerEntity>();
objCustomerData.CustomerCode = txtCustomerCode.Text;
objCustomerData.CustomerName = txtCustomerName.Text;
objContext.SubmitChanges();

LINQ 更新的最终代码

下面是最终的 LINQ 更新查询的外观

DataContext objContext = new DataContext(strConnectionString);
var MyQuery = from objCustomer in objContext.GetTable<clsCustomerEntity>()
where objCustomer.CustomerId == Convert.ToInt16(txtCustomerId.Text)
select objCustomer;
clsCustomerEntity objCustomerData = (clsCustomerEntity)MyQuery.First<clsCustomerEntity>();
objCustomerData.CustomerCode = txtCustomerCode.Text;
objCustomerData.CustomerName = txtCustomerName.Text;
objContext.SubmitChanges();

步骤 4:使用 LINQ 删除

让我们来看下一个数据库操作,删除。

DeleteOnSubmit

我们不会重复之前创建数据上下文和选择 LINQ 对象等步骤,这些步骤都在上一节中进行了说明。要从内存中删除对象,我们需要调用 DeleteOnSubmit();要从数据库中删除,我们需要调用 SubmitChanges()

objContext.GetTable<clsCustomerEntity>().DeleteOnSubmit(objCustomerData);
objContext.SubmitChanges();

步骤 5:自解释的 LINQ 选择和读取

现在进入最后一步,根据条件选择和读取 LINQ 对象。下面是一个代码片段,展示了如何触发 LINQ 查询并将对象值设置到 ASP.NET UI。

DataContext objContext = new DataContext(strConnectionString);

var MyQuery = from objCustomer in objContext.GetTable<clsCustomerEntity>()
where objCustomer.CustomerId == Convert.ToInt16(txtCustomerId.Text)
select objCustomer;

clsCustomerEntity objCustomerData = (clsCustomerEntity)MyQuery.First<clsCustomerEntity>();
txtCustomerCode.Text = objCustomerData.CustomerCode;
txtCustomerName.Text = objCustomerData.CustomerName;

如需进一步阅读,请观看以下面试准备视频和分步视频系列。

© . All rights reserved.