Optimizing Data Access and Messaging-Performing Entity Group Transactions

http://msdn.microsoft.com/en-us/library/dd894038.aspx

Updated: September 13, 2011

The Table service supports batch transactions on entities that are in the same table and belong to the same partition group. Multiple Insert EntityUpdate EntityMerge EntityDelete EntityInsert Or Replace Entity, and Insert Or Merge Entity operations are supported within a single transaction.

You can perform entity group transactions either via REST or by using the .NET Client Library for ADO.NET Data Services.

An entity group transaction must meet the following requirements:

  • All entities subject to operations as part of the transaction must have the same PartitionKey value.

  • An entity can appear only once in the transaction, and only one operation may be performed against it. 

  • The transaction can include at most 100 entities, and its total payload may be no more than 4 MB in size.

  • All entities are subject to the limitations described in Understanding the Table Service Data Model.

The semantics for entity group transactions are defined by the ADO.NET Data Services Specifications. The ADO.NET Data Services specification defines the following concepts for batch requests:

  • change set is a group of one or more insert, update, or delete operations.

  • batch is a container of operations, including one or more change sets and query operations.

The Table service supports a subset of the functionality defined by ADO.NET Data Services:

  • The Table service supports only a single change set within a batch. The change set can include multiple insert, update, and delete operations. If a batch includes more than one change set, the first change set will be processed by the service, and additional change sets will be rejected with status code 400 (Bad Request).

ImportantImportant
Multiple operations against a single entity are not permitted within a change set.

  • Note that a query operation is not permitted within a batch that contains insert, update, or delete operations; it must be submitted singly in the batch. 

  • Operations within a change set are processed atomically; that is, all operations in the change set either succeed or fail. Operations are processed in the order they are specified in the change set.

  • The Table service does not support linking operations in a change set.

  • The Table service supports a maximum of 100 operations in a change set.

The following sections describe how to construct a batch request and how to interpret the batch response, and show samples of each.

To perform a batch request via REST, specify the $batch option on the request URI. For example:

http://myaccount.table.core.windows.net/$batch

Note that the request URI does not include the table name.

A batch request is sent to the server with a single POST directive. This request must include the x-ms-version header; the header's value must be set to 2009-04-14.

The XML payload is a multi-part MIME message containing the batch and the change set. The payload includes two MIME boundaries:

  • A batch boundary encompasses the change set.

  • A change set boundary separates individual insert, update, and delete operations in the batch.

An individual request within the change set is identical to a request made when that operation is being called by itself.

To specify the If-Match header on an update, merge, or delete operation, include the header in the set of request headers for the appropriate operation in the change set.

For detailed information about constructing the batch request, including the request headers, the batch boundary, and the change set boundary, see the .NET Client Library for ADO.NET Data Services.

The following example shows a batch request containing two Insert Entity operations, a Merge Entity operation, and a Delete Entityoperation.

POST /$batch HTTP/1.1
User-Agent: Microsoft ADO.NET Data Services
x-ms-version: 2009-04-14
x-ms-date: Thu, 30 Apr 2009 20:45:13 GMT
Authorization: SharedKeyLite myaccount:asOEzsCDS7YEe6oi+bx47KMwbXL0lYZCOlR/oc3FReQ=
Accept: application/atom+xml,application/xml
Accept-Charset: UTF-8
DataServiceVersion: 1.0;NetFx
MaxDataServiceVersion: 2.0;NetFx
Content-Type: multipart/mixed; boundary=batch_a1e9d677-b28b-435e-a89e-87e6a768a431
Host: MyHostName:10002
Content-Length: ###

--batch_a1e9d677-b28b-435e-a89e-87e6a768a431
Content-Type: multipart/mixed; boundary=changeset_8a28b620-b4bb-458c-a177-0959fb14c977

--changeset_8a28b620-b4bb-458c-a177-0959fb14c977
Content-Type: application/http
Content-Transfer-Encoding: binary

POST http://myaccount.tables.core.windows.net/Blogs HTTP/1.1
Content-ID: 1
Content-Type: application/atom+xml;type=entry
Content-Length: ###

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
  <title />
  <updated>2009-04-30T20:45:13.7155321Z</updated>
  <author>
    <name />
  </author>
  <id />
  <content type="application/xml">
    <m:properties>
      <d:PartitionKey>Channel_19</d:PartitionKey>
      <d:RowKey>1</d:RowKey>
      <d:Timestamp m:type="Edm.DateTime">0001-01-01T00:00:00</d:Timestamp>
      <d:Rating m:type="Edm.Int32">9</d:Rating>
      <d:Text>.NET...</d:Title>
    </m:properties>
  </content>
</entry>
--changeset_8a28b620-b4bb-458c-a177-0959fb14c977
Content-Type: application/http
Content-Transfer-Encoding: binary

POST http://myaccount.tables.core.windows.net/Blogs HTTP/1.1
Content-ID: 2
Content-Type: application/atom+xml;type=entry
Content-Length: ###

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
  <title />
  <updated>2009-04-30T20:45:13.7155321Z</updated>
  <author>
    <name />
  </author>
  <id />
  <content type="application/xml">
    <m:properties>
      <d:PartitionKey>Channel_19</d:PartitionKey>
      <d:RowKey>2</d:RowKey>
      <d:Timestamp m:type="Edm.DateTime">0001-01-01T00:00:00</d:Timestamp>
      <d:Rating m:type="Edm.Int32">9</d:Rating>
      <d:Text>Azure...</d:Title>
    </m:properties>
  </content>
</entry>
--changeset_8a28b620-b4bb-458c-a177-0959fb14c977
Content-Type: application/http
Content-Transfer-Encoding: binary

MERGE http://myaccount.tables.core.windows.net/Blogs(PartitionKey='Channel_19', RowKey='3') HTTP/1.1
Content-ID: 3
Content-Type: application/atom+xml;type=entry
Content-Length: ###

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
  <title />
  <updated>2009-04-30T20:44:09.8869156Z</updated>
  <author>
    <name />
  </author>
  <id>http://myaccount.tables.core.windows.net/Blogs(PartitionKey='Channel_19',RowKey='3)</id>

  <content type="application/xml">
    <m:properties>
      <d:PartitionKey>Channel_19</d:PartitionKey>
      <d:RowKey>3</d:RowKey>
      <d:Timestamp m:type="Edm.DateTime">0001-01-01T00:00:00</d:Timestamp>
      <d:Rating m:type="Edm.Int32">9</d:Rating>
      <d:Text>PDC 2008...</d:Title>
    </m:properties>
  </content>
</entry>
--changeset_8a28b620-b4bb-458c-a177-0959fb14c977
Content-Type: application/http
Content-Transfer-Encoding: binary

DELETE http://myaccount.tables.core.windows.net/Blogs(PartitionKey='Channel_19', RowKey='4') Content-ID: 4
Content-Type: application/atom+xml;type=entry
Content-Length: ###

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
  <title />
  <updated>2009-04-30T20:44:09.8869156Z</updated>
  <author>
    <name />
  </author>
  <id>http://myaccount.tables.core.windows.net/Blogs(PartitionKey='Channel_19',RowKey='3)</id>

  <content type="application/xml">
    <m:properties>
      <d:PartitionKey>Channel_19</d:PartitionKey>
      <d:RowKey>3</d:RowKey>
      <d:Timestamp m:type="Edm.DateTime">0001-01-01T00:00:00</d:Timestamp>
      <d:Rating m:type="Edm.Int32">9</d:Rating>
      <d:Text>PDC 2008...</d:Title>
    </m:properties>
  </content>
</entry>
--changeset_8a28b620-b4bb-458c-a177-0959fb14c977--
--batch_a1e9d677-b28b-435e-a89e-87e6a768a431--

The following example shows a batch request for a query. Note that only a single query may be included in the change set.

POST /$batch HTTP/1.1
User-Agent: Microsoft ADO.NET Data Services
x-ms-version: 2009-04-14
x-ms-date: Thu, 30 Apr 2009 20:45:13 GMT
Authorization: SharedKeyLite myaccount:asOEzsCDS7YEe6oi+bx47KMwbXL0lYZCOlR/oc3FReQ=
Accept: application/atom+xml,application/xml
Accept-Charset: UTF-8
DataServiceVersion: 1.0;NetFx
MaxDataServiceVersion: 1.0;NetFx
Content-Type: multipart/mixed; boundary=batch_f351702c-c8c8-48c6-af2c-91b809c651ce
Content-Length: ###

--batch_f351702c-c8c8-48c6-af2c-91b809c651ce
Content-Type: application/http
Content-Transfer-Encoding: binary

GET http:// myaccount.tables.core.windows.net/Blogs(PartitionKey='Channel_19',RowKey='2') HTTP/1.1

--batch_f351702c-c8c8-48c6-af2c-91b809c651ce--

The response returns an overall status code for the batch request, and individual status codes and result fragments for each operation in the change set. The response is a multi-part MIME message that includes a batch boundary and a change set boundary.

The Table service returns a status code for the entire batch request, and one or more status codes for the operations in the change set, depending on whether they succeeded or failed.

Assuming that the batch request has been properly authenticated and has been successfully received by the Table service, the batch request returns status code 202 (Accepted), even if one of the operations in the change set fails. If the batch request itself fails, it fails before any operation in the change set is executed. For example, the batch request may fail due to an authentication error, in which case the status code will indicate that failure.

noteNote
If you are using the .NET Client Library to process a batch request that fails prior to executing the operations in the change set, note that the .NET Client Library returns a WebException for this kind of failure, rather than a DataServiceRequestException.

The operations in a change set are processed atomically; that is, either all operations in the batch succeed, or the entire batch fails. The Table service continues processing operations in the change set until one fails. If an operation fails, all preceding operations in the batch are rolled back. Additionally, entity group transactions execute with snapshot isolation.

The status code for an individual operation within a change set appears within the change set response. When an individual operation fails, the response for the change set indicates status code 400 (Bad Request). Additional error information within the response indicates which operation failed by returning the index of that operation. The index is the sequence number of the command in the payload.

noteNote
The Table service does not guarantee the order in which operations are executed.

For an example, see the sample error response below.

The following example shows the response for the batch operations sent in the sample request shown above.

HTTP/1.1 202 Accepted
Cache-Control: no-cache
Transfer-Encoding: chunked
Content-Type: multipart/mixed; boundary=batchresponse_dc0fea8c-ed83-4aa8-ac9b-bf56a2d46dfb
Server: Windows-Azure-Table/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: b4b49b3e-19a9-4091-a280-da76a09da8d4
Date: Thu, 30 Apr 2009 20:44:09 GMT

334
batchresponse_dc0fea8c-ed83-4aa8-ac9b-bf56a2d46dfb 
Content-Type: multipart/mixed; boundary=--changesetresponse_8a28b620-b4bb-458c-a177-0959fb14c977

--changesetresponse_8a28b620-b4bb-458c-a177-0959fb14c977
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 201 Created
Content-ID: 1
Content-Type: application/atom+xml;charset=utf-8
Cache-Control: no-cache
ETag: W/"datetime'2009-04-30T20%3A44%3A09.5789464Z'"
Location: http://myaccount.tables.core.windows.net/Blogs(PartitionKey='Channel_19',RowKey='1')
DataServiceVersion: 1.0;

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<entry xml:base="http:// myaccount.tables.core.windows.net/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:etag="W/&quot;datetime'2009-04-30T20%3A44%3A09.5789464Z'&quot;" xmlns="http://www.w3.org/2005/Atom">
  <id> http://myaccount.tables.core.windows.net/Blogs(PartitionKey='Channel_19',RowKey='1')</id>
  <title type="text"></title>
  <updated>2009-04-30T20:44:09Z</updated>
  <author>
    <name />
  </author>
  <link rel="edit" title="Blogs" href=" Blogs(PartitionKey='Channel_19',RowKey='1')" />
  <category term="myaccount.Blogs" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
  <content type="application/xml">
    <m:properties>
      <d:PartitionKey>Channel_19</d:PartitionKey>
       <d:RowKey>1</d:RowKey>
       <d:Timestamp m:type="Edm.DateTime">2009-04-30T20:44:09.5789464Z</d:Timestamp>
       <d:Text>.Net...</d:RowKey>
      <d:Rating m:type="Edm.Int32">9</d:Rating>
    </m:properties>
  </content>
</entry>

--changesetresponse_8a28b620-b4bb-458c-a177-0959fb14c977
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 201 Created
Content-ID: 2
Content-Type: application/atom+xml;charset=utf-8
Cache-Control: no-cache
ETag: W/"datetime'2009-04-30T20%3A44%3A09.5789464Z'"
Location: http://myaccount.tables.core.windows.net/Blogs(PartitionKey='Channel_19',RowKey='2')
DataServiceVersion: 1.0;

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<entry xml:base="http:// myaccount.tables.core.windows.net/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:etag="W/&quot;datetime'2009-04-30T20%3A44%3A09.5789464Z'&quot;" xmlns="http://www.w3.org/2005/Atom">
  <id> http://myaccount.tables.core.windows.net/Blogs(PartitionKey='Channel_19',RowKey='2')</id>
  <title type="text"></title>
  <updated>2009-04-30T20:44:09Z</updated>
  <author>
    <name />
  </author>
  <link rel="edit" title="Blogs" href=" Blogs(PartitionKey='Channel_19',RowKey='2')" />
  <category term="myaccount.Blogs" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
  <content type="application/xml">
    <m:properties>
      <d:PartitionKey>Channel_19</d:PartitionKey>
       <d:RowKey>2</d:RowKey>
       <d:Timestamp m:type="Edm.DateTime">2009-04-30T20:44:09.5789464Z</d:Timestamp>
       <d:Text>Azure...</d:RowKey>
      <d:Rating m:type="Edm.Int32">9</d:Rating>
    </m:properties>
  </content>
</entry>

--changesetresponse_8a28b620-b4bb-458c-a177-0959fb14c977
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 204 No Content
Content-ID: 3
Cache-Control: no-cache
ETag: W/"datetime'2009-04-30T20%3A44%3A10.0019041Z'"
DataServiceVersion: 1.0;

--changesetresponse_8a28b620-b4bb-458c-a177-0959fb14c977
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 204 No Content
Content-ID: 4
Cache-Control: no-cache
DataServiceVersion: 1.0;

--changesetresponse_8a28b620-b4bb-458c-a177-0959fb14c977--
--batchresponse_4c637ba4-b2f8-40f8-8856-c2d10d163a83--

0
Sample Response for Queries
The following example shows the response for the query sent in the sample request shown above. 
HTTP/1.1 202 Accepted
Cache-Control: no-cache
Transfer-Encoding: chunked
Content-Type: multipart/mixed; boundary=batchresponse_4c637ba4-b2f8-40f8-8856-c2d10d163a83
Server: Windows-Azure-Table/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: 9202c4a1-43af-4dc0-baca-aa71f7a7407b
Date: Thu, 30 Apr 2009 20:44:10 GMT

1DC1
--batchresponse_4c637ba4-b2f8-40f8-8856-c2d10d163a83
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 200 OK
Content-Type: application/atom+xml;charset=utf-8
Cache-Control: no-cache
ETag: W/"datetime'2009-04-30T20%3A44%3A10.0019041Z'"
DataServiceVersion: 1.0;

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<entry xml:base="http://127.0.0.1:10002/testaccount1/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:etag="W/&quot;datetime'2009-04-30T20%3A44%3A10.0019041Z'&quot;" xmlns="http://www.w3.org/2005/Atom">
    <id> http://myaccount.tables.core.windows.net/Blogs(PartitionKey='Channel_19',RowKey='1')</id>
  <title type="text"></title>
  <updated>2009-04-30T20:44:10Z</updated>
  <author>
    <name />
  </author>
  <link rel="edit" title="Blogs" href=" Blogs(PartitionKey='Channel_19',RowKey='2')" />
  <category term="myaccount.Blogs" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
  <content type="application/xml">
    <m:properties>
      <d:PartitionKey>Channel_19</d:PartitionKey>
       <d:RowKey>2</d:RowKey>
       <d:Timestamp m:type="Edm.DateTime">2009-04-30T20:44:09.5789464Z</d:Timestamp>
       <d:Text>.Net...</d:RowKey>
      <d:Rating m:type="Edm.Int32">9</d:Rating>
    </m:properties>
  </content>
</entry>
--batchresponse_4c637ba4-b2f8-40f8-8856-c2d10d163a83--

0

The following example shows the response for the query sent in the sample request shown above.

HTTP/1.1 202 Accepted
Cache-Control: no-cache
Transfer-Encoding: chunked
Content-Type: multipart/mixed; boundary=batchresponse_4c637ba4-b2f8-40f8-8856-c2d10d163a83
Server: Windows-Azure-Table/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: 9202c4a1-43af-4dc0-baca-aa71f7a7407b
Date: Thu, 30 Apr 2009 20:44:10 GMT

1DC1
--batchresponse_4c637ba4-b2f8-40f8-8856-c2d10d163a83
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 200 OK
Content-Type: application/atom+xml;charset=utf-8
Cache-Control: no-cache
ETag: W/"datetime'2009-04-30T20%3A44%3A10.0019041Z'"
DataServiceVersion: 1.0;

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<entry xml:base="http://127.0.0.1:10002/testaccount1/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:etag="W/&quot;datetime'2009-04-30T20%3A44%3A10.0019041Z'&quot;" xmlns="http://www.w3.org/2005/Atom">
    <id> http://myaccount.tables.core.windows.net/Blogs(PartitionKey='Channel_19',RowKey='1')</id>
  <title type="text"></title>
  <updated>2009-04-30T20:44:10Z</updated>
  <author>
    <name />
  </author>
  <link rel="edit" title="Blogs" href=" Blogs(PartitionKey='Channel_19',RowKey='2')" />
  <category term="myaccount.Blogs" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
  <content type="application/xml">
    <m:properties>
      <d:PartitionKey>Channel_19</d:PartitionKey>
       <d:RowKey>2</d:RowKey>
       <d:Timestamp m:type="Edm.DateTime">2009-04-30T20:44:09.5789464Z</d:Timestamp>
       <d:Text>.Net...</d:RowKey>
      <d:Rating m:type="Edm.Int32">9</d:Rating>
    </m:properties>
  </content>
</entry>
--batchresponse_4c637ba4-b2f8-40f8-8856-c2d10d163a83--

0

The following example shows a response from a batch request containing an operation that failed. Note that the batch response returns status code 202 (Accepted), but the individual operation that failed returns status code 400 (Bad Request). The additional error information is included in the response body for the failed operation. The code element specifies the storage service error code, whereas the message element begins with the index of the failed operation, followed by the error message string. To determine which operation failed, parse the index value from the message. Operations are indexed beginning at zero.

In this example, note that the operation that failed was the fourth operation in the change set. Within the message element, the message begins with the numeral 3, followed by the extended error information.

<message xml:lang="en-US">3:One of the request inputs is not valid.</message>

Here is the complete response:

HTTP/1.1 202 Accepted
Cache-Control: no-cache
Transfer-Encoding: chunked
Content-Type: multipart/mixed; boundary=batchresponse_7ab1553a-7dd6-44e7-8107-bf1ea1ab1876
Server: Windows-Azure-Table/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: 45ac953e-a4a5-42ba-9b4d-97bf74a8a32e
Date: Thu, 30 Apr 2009 20:45:13 GMT

6E7
--batchresponse_7ab1553a-7dd6-44e7-8107-bf1ea1ab1876
Content-Type: multipart/mixed; boundary=changesetresponse_6cc856b4-8cb9-41eb-b8d2-bb73475c6cec

--changesetresponse_6cc856b4-8cb9-41eb-b8d2-bb73475c6cec
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 400 Bad Request
Content-ID: 4
Content-Type: application/xml
Cache-Control: no-cache
DataServiceVersion: 1.0;

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
  <code>InvalidInput</code>
  <message xml:lang="en-US">3:One of the request inputs is not valid.</message>
</error>
--changesetresponse_6cc856b4-8cb9-41eb-b8d2-bb73475c6cec--
--batchresponse_7ab1553a-7dd6-44e7-8107-bf1ea1ab1876--

0

The Table service supports using the .NET Client Library for ADO.NET Data Services to perform entity group transactions. To submit a changeset containing insert, update, and delete operations, call the SaveChanges method of the DataServicesContext object, with theSaveChangesOptions.Batch option. You can also call the BeginSaveChanges and EndSaveChanges methods to save changes asynchronously.

You can execute a single query within a single batch by calling the ExecuteBatch method. To execute a single query asynchronously, callBeginExecuteBatch and EndExecuteBatch. Note that calling these methods with a batch containing more than one query is not currently supported.

The following code excerpt demonstrates using the SaveChanges method to insert a set of entities:

for (int index = 0; index < 20; index++)
{
  Blog blog = new Blog(
              userId /* partition key */,
              string.Format("{0:D19}", i) /* row key - blog id*/,
              DateTime.UtcNow /* blog creation date */,
              title,
              message);
       context.AddObject(blog);
}

// All operations above are executed as a single batch request.
DataServiceResponse response = context.SaveChanges(SaveChangesOptions.Batch);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值