예제 #1
0
 public void ApplyDataChanges(int sourceId, DataResponse response)
 {
     DataSet targetDS = Target;
     if (targetDS != null)
     {
         int targetID;
         if (targetVars.TryGetValue(sourceId, out targetID))
             targetDS.Variables.GetByID(targetID).PutData(response.DataRequest.Origin, response.Data);
     }
 }
		/// <summary>
		/// Gets data from several variables atomically with a guarantee that the data belong to the same DataSet version.
		/// </summary>
		/// <param name="requests">Data requests describing what data is to be returned.</param>
		/// <returns>All requested data.</returns>
		/// <remarks>
		/// <para>
		/// The problem is to get consistent data from one version of a DataSet.
		/// A typical program flow for working with data from several related variables 
		/// involve several consequent calls of the <see cref="Variable.GetData()"/>. 
		/// If the data set is being changed in the background by another process, 
		/// the data returned may come from different versions (see <see cref="DataSet.Version"/>). 
		/// This is inappropriate for many applications.
		/// </para>
		/// <para>
		/// The solution is to use <see cref="GetMultipleData"/> method which performs several
		/// <see cref="Variable.GetData()"/> operations atomically and guarantees that 
		/// all returned arrays belong to the same DataSet version.
		/// </para>
		/// <example>
		/// The following example gets data from two variables atomically:
		/// <code>
		/// DataSet ds = . . .;
		/// var v1 = ds.AddVariable&lt;string&gt;("v1", "x");
		/// var v2 = ds.AddVariable&lt;double&gt;("v2", "x", "y");
		/// 
		/// . . .
		/// 
		/// MultipleDataResponse response = ds.GetMultipleData(
		///			// requesting 10 first elements from "v1":
		///			DataRequest.GetData(v1, null, new int[1] { 10 }), 
		///			// requesting 10x20 first elements from "v2":
		///			DataRequest.GetData(v2, null, new int[2] { 10, 20 }));
		///
		/// DataResponse r1 = response[v1.ID];
		/// DataResponse r2 = response[v2.ID];
		///	
		/// // All the data belong to the version "response.Version".
		/// string[] d1 = (string[]) r1.Data;
		/// double[,] d2 = (double[,]) r2.Data;
		/// </code>
		/// </example>
		/// </remarks>
		/// <seealso cref="DataRequest"/>
		/// <seealso cref="MultipleDataResponse"/>
		/// <exception cref="ArgumentNullException"><paramref name="requests"/> or one of its elements is null.</exception>
		/// <exception cref="ArgumentException">One of requested variable belongs to another DataSet.</exception>
		/// <exception cref="ApplicationException">Version of the DataSet unexpectedly changed during getting data.</exception>
		public virtual MultipleDataResponse GetMultipleData(params DataRequest[] requests)
		{
			if (requests == null)
				throw new ArgumentNullException("requests");
			if (requests.Length == 0)
				return new MultipleDataResponse(Version, new DataResponse[0]);

			foreach (var r in requests)
			{
				if (r == null)
					throw new ArgumentException("One of parameter's elements is null", "requests");
				if (r.Variable.DataSet != this)
					throw new ArgumentException("Cannot get data from another's variable");
			}

			DataResponse[] responses = new DataResponse[requests.Length];

			lock (this)
			{
				int version = this.Version;
				for (int i = 0; i < requests.Length; i++)
				{
					DataRequest r = requests[i];
					Array data;
					if (r.Stride == null)
						data = r.Variable.GetData(r.Origin, r.Shape);
					else
						data = r.Variable.GetData(r.Origin, r.Stride, r.Shape);
					DataResponse resp = new DataResponse(r, data);
					responses[i] = resp;
				}

				if (this.Version != version)
					throw new CannotPerformActionException("Version has changed");

				return new MultipleDataResponse(version, responses);
			}
		}
		internal MultipleDataResponse(int version, DataResponse[] responses)
		{
			this.responses = responses;
			this.version = version;
		}