Search Results for

    Show / Hide Table of Contents

    Using Entity Framework datasources (C# / netframework)

    Note

    This demo is available in your FlexCel installation at <FlexCel Install Folder>\samples\csharp\VS2022\netframework\20.Reports\24.Entity Framework Reports and also at https:​//​github.​com/​tmssoftware/​TMS-​FlexCel.​NET-​demos/​tree/​master/​csharp/​VS2022/​netframework/​Modules/​20.​Reports/​24.​Entity Framework Reports

    Overview

    Note

    To run this example, you need to have SQL Server (LocalDB) installed. For this reason, and because it uses NuGet, this demo doesn't run from MainDemo. You need to open this solution and run it alone.

    While you can use any generic IQueryable<T> object as a source of reports, here we provide a concrete example of redoing the "range reports" demo using Entity Framework.

    Concepts

    • Entity Framework reports should be run inside a serializable or snapshot transaction. While snapshot transactions are preferred as they won't block other users from changing the data while the report is running, in this example we use serializable (Because LocalDB doesn't support snapshot)

    • Here we have an implicit relationship between categories and products, so we don't need to add an explicit one. The report will just work.

    Files

    Category.cs

    //------------------------------------------------------------------------------
    // <auto-generated>
    //     This code was generated from a template.
    //
    //     Manual changes to this file may cause unexpected behavior in your application.
    //     Manual changes to this file will be overwritten if the code is regenerated.
    // </auto-generated>
    //------------------------------------------------------------------------------
    
    namespace EntityFrameworkReports
    {
        using System;
        using System.Collections.Generic;
    
        public partial class Category
        {
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
            public Category()
            {
                this.Products = new HashSet<Product>();
            }
    
            public int CategoryID { get; set; }
            public string CategoryName { get; set; }
            public string Description { get; set; }
            public byte[] Picture { get; set; }
        
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
            public virtual ICollection<Product> Products { get; set; }
        }
    }
    

    Customer.cs

    //------------------------------------------------------------------------------
    // <auto-generated>
    //     This code was generated from a template.
    //
    //     Manual changes to this file may cause unexpected behavior in your application.
    //     Manual changes to this file will be overwritten if the code is regenerated.
    // </auto-generated>
    //------------------------------------------------------------------------------
    
    namespace EntityFrameworkReports
    {
        using System;
        using System.Collections.Generic;
    
        public partial class Customer
        {
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
            public Customer()
            {
                this.Orders = new HashSet<Order>();
                this.CustomerDemographics = new HashSet<CustomerDemographic>();
            }
    
            public string CustomerID { get; set; }
            public string CompanyName { get; set; }
            public string ContactName { get; set; }
            public string ContactTitle { get; set; }
            public string Address { get; set; }
            public string City { get; set; }
            public string Region { get; set; }
            public string PostalCode { get; set; }
            public string Country { get; set; }
            public string Phone { get; set; }
            public string Fax { get; set; }
        
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
            public virtual ICollection<Order> Orders { get; set; }
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
            public virtual ICollection<CustomerDemographic> CustomerDemographics { get; set; }
        }
    }
    

    CustomerDemographic.cs

    //------------------------------------------------------------------------------
    // <auto-generated>
    //     This code was generated from a template.
    //
    //     Manual changes to this file may cause unexpected behavior in your application.
    //     Manual changes to this file will be overwritten if the code is regenerated.
    // </auto-generated>
    //------------------------------------------------------------------------------
    
    namespace EntityFrameworkReports
    {
        using System;
        using System.Collections.Generic;
    
        public partial class CustomerDemographic
        {
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
            public CustomerDemographic()
            {
                this.Customers = new HashSet<Customer>();
            }
    
            public string CustomerTypeID { get; set; }
            public string CustomerDesc { get; set; }
        
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
            public virtual ICollection<Customer> Customers { get; set; }
        }
    }
    

    Employee.cs

    //------------------------------------------------------------------------------
    // <auto-generated>
    //     This code was generated from a template.
    //
    //     Manual changes to this file may cause unexpected behavior in your application.
    //     Manual changes to this file will be overwritten if the code is regenerated.
    // </auto-generated>
    //------------------------------------------------------------------------------
    
    namespace EntityFrameworkReports
    {
        using System;
        using System.Collections.Generic;
    
        public partial class Employee
        {
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
            public Employee()
            {
                this.Employees1 = new HashSet<Employee>();
                this.Orders = new HashSet<Order>();
                this.Territories = new HashSet<Territory>();
            }
    
            public int EmployeeID { get; set; }
            public string LastName { get; set; }
            public string FirstName { get; set; }
            public string Title { get; set; }
            public string TitleOfCourtesy { get; set; }
            public Nullable<System.DateTime> BirthDate { get; set; }
            public Nullable<System.DateTime> HireDate { get; set; }
            public string Address { get; set; }
            public string City { get; set; }
            public string Region { get; set; }
            public string PostalCode { get; set; }
            public string Country { get; set; }
            public string HomePhone { get; set; }
            public string Extension { get; set; }
            public byte[] Photo { get; set; }
            public string Notes { get; set; }
            public Nullable<int> ReportsTo { get; set; }
            public string PhotoPath { get; set; }
        
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
            public virtual ICollection<Employee> Employees1 { get; set; }
            public virtual Employee Employee1 { get; set; }
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
            public virtual ICollection<Order> Orders { get; set; }
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
            public virtual ICollection<Territory> Territories { get; set; }
        }
    }
    

    Form1.cs

    using System;
    using System.Drawing;
    using System.Collections;
    using System.ComponentModel;
    using System.Windows.Forms;
    using System.Data;
    using System.IO;
    using System.Diagnostics;
    using System.Reflection;
    using FlexCel.Core;
    using FlexCel.XlsAdapter;
    using FlexCel.Report;
    using System.Transactions;
    using System.Configuration;
    
    
    namespace EntityFrameworkReports
    {
        /// <summary>
        /// Summary description for Form1.
        /// </summary>
        public partial class mainForm : System.Windows.Forms.Form
        {
    
            public mainForm()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, System.EventArgs e)
            {
                AutoRun();
            }
    
            public void AutoRun()
            {
                using (FlexCelReport ordersReport = new FlexCelReport(true))
                {
                    string DataPath = Path.Combine(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), ".."), "..") + Path.DirectorySeparatorChar;
                    ordersReport.SetValue("Date", DateTime.Now);
    
                    using (northwndEntities Northwind = new northwndEntities())
                    {
                        ordersReport.AddTable("Categories", Northwind.Categories);
                        ordersReport.AddTable("Products", Northwind.Products);
    
                        if (saveFileDialog1.ShowDialog() == DialogResult.OK)
                        {
                            TransactionOptions transactionOptions = new TransactionOptions();
                            transactionOptions.IsolationLevel = System.Transactions.IsolationLevel.Serializable; //it would be better to sue Snapshot here, but it isn't supported by SQL Sever CE
                            using (TransactionScope transactionScope = new TransactionScope(TransactionScopeOption.Required, transactionOptions))
                            {
                                ordersReport.Run(DataPath + "Entity Framework Reports.template.xls", saveFileDialog1.FileName);
                                transactionScope.Complete();
                            }
    
                            if (MessageBox.Show("Do you want to open the generated file?", "Confirm", MessageBoxButtons.YesNo) == DialogResult.Yes)
                            {
                                using (Process p = new Process())
                                {               
                                    p.StartInfo.FileName = saveFileDialog1.FileName;
                                    p.StartInfo.UseShellExecute = true;
                                    p.Start();
                                }
                            }
                        }
                    }
                }
            }
    
            private void btnCancel_Click(object sender, System.EventArgs e)
            {
                Close();
            }
        }
    
    }
    

    Form1.Designer.cs

    using System;
    using System.Drawing;
    using System.Collections;
    using System.ComponentModel;
    using System.Windows.Forms;
    using System.Data;
    using System.IO;
    using System.Diagnostics;
    using System.Reflection;
    using FlexCel.Core;
    using FlexCel.XlsAdapter;
    using FlexCel.Report;
    
    namespace EntityFrameworkReports
    {
        public partial class mainForm : System.Windows.Forms.Form
        {
            private System.Windows.Forms.Button button1;
            private System.Windows.Forms.SaveFileDialog saveFileDialog1;
            private System.Windows.Forms.Label label1;
            private System.Windows.Forms.Button btnCancel;
            /// <summary>
            /// Required designer variable.
            /// </summary>
            private System.ComponentModel.Container components = null;
    
            /// <summary>
            /// Clean up any resources being used.
            /// </summary>
            protected override void Dispose( bool disposing )
            {
                if( disposing )
                {
                    if (components != null) 
                    {
                        components.Dispose();
                    }
                }
                base.Dispose( disposing );
            }
    
            #region Windows Form Designer generated code
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {
                this.button1 = new System.Windows.Forms.Button();
                this.saveFileDialog1 = new System.Windows.Forms.SaveFileDialog();
                this.label1 = new System.Windows.Forms.Label();
                this.btnCancel = new System.Windows.Forms.Button();
                this.SuspendLayout();
                // 
                // button1
                // 
                this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
                this.button1.BackColor = System.Drawing.Color.Green;
                this.button1.ForeColor = System.Drawing.Color.White;
                this.button1.Location = new System.Drawing.Point(152, 88);
                this.button1.Name = "button1";
                this.button1.Size = new System.Drawing.Size(112, 23);
                this.button1.TabIndex = 0;
                this.button1.Text = "GO!";
                this.button1.UseVisualStyleBackColor = false;
                this.button1.Click += new System.EventHandler(this.button1_Click);
                // 
                // saveFileDialog1
                // 
                this.saveFileDialog1.Filter = "Excel Files|*.xls";
                this.saveFileDialog1.RestoreDirectory = true;
                // 
                // label1
                // 
                this.label1.Location = new System.Drawing.Point(24, 24);
                this.label1.Name = "label1";
                this.label1.Size = new System.Drawing.Size(272, 24);
                this.label1.TabIndex = 2;
                this.label1.Text = "Press \"GO\" to create a database Report.";
                // 
                // btnCancel
                // 
                this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
                this.btnCancel.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))));
                this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
                this.btnCancel.ForeColor = System.Drawing.Color.White;
                this.btnCancel.Location = new System.Drawing.Point(272, 88);
                this.btnCancel.Name = "btnCancel";
                this.btnCancel.Size = new System.Drawing.Size(112, 23);
                this.btnCancel.TabIndex = 3;
                this.btnCancel.Text = "Cancel";
                this.btnCancel.UseVisualStyleBackColor = false;
                this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
                // 
                // mainForm
                // 
                this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
                this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
                this.ClientSize = new System.Drawing.Size(416, 133);
                this.Controls.Add(this.btnCancel);
                this.Controls.Add(this.label1);
                this.Controls.Add(this.button1);
                this.Name = "mainForm";
                this.Text = "Entity Framework Report";
                this.ResumeLayout(false);
    
            }
            #endregion
        }
    }
    

    ModelNorthwind.Context.cs

    //------------------------------------------------------------------------------
    // <auto-generated>
    //     This code was generated from a template.
    //
    //     Manual changes to this file may cause unexpected behavior in your application.
    //     Manual changes to this file will be overwritten if the code is regenerated.
    // </auto-generated>
    //------------------------------------------------------------------------------
    
    namespace EntityFrameworkReports
    {
        using System;
        using System.Data.Entity;
        using System.Data.Entity.Infrastructure;
    
        public partial class northwndEntities : DbContext
        {
            public northwndEntities()
                : base("name=northwndEntities")
            {
            }
    
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                throw new UnintentionalCodeFirstException();
            }
    
            public virtual DbSet<Category> Categories { get; set; }
            public virtual DbSet<CustomerDemographic> CustomerDemographics { get; set; }
            public virtual DbSet<Customer> Customers { get; set; }
            public virtual DbSet<Employee> Employees { get; set; }
            public virtual DbSet<Order_Detail> Order_Details { get; set; }
            public virtual DbSet<Order> Orders { get; set; }
            public virtual DbSet<Product> Products { get; set; }
            public virtual DbSet<Region> Regions { get; set; }
            public virtual DbSet<Shipper> Shippers { get; set; }
            public virtual DbSet<Supplier> Suppliers { get; set; }
            public virtual DbSet<Territory> Territories { get; set; }
        }
    }
    

    ModelNorthwind.cs

    //------------------------------------------------------------------------------
    // <auto-generated>
    //     This code was generated from a template.
    //
    //     Manual changes to this file may cause unexpected behavior in your application.
    //     Manual changes to this file will be overwritten if the code is regenerated.
    // </auto-generated>
    //------------------------------------------------------------------------------
    

    ModelNorthwind.Designer.cs

    // T4 code generation is enabled for model ''. 
    // To enable legacy code generation, change the value of the 'Code Generation Strategy' designer
    // property to 'Legacy ObjectContext'. This property is available in the Properties Window when the model
    // is open in the designer.
    
    // If no context and entity classes have been generated, it may be because you created an empty model but
    // have not yet chosen which version of Entity Framework to use. To generate a context class and entity
    // classes for your model, open the model in the designer, right-click on the designer surface, and
    // select 'Update Model from Database...', 'Generate Database from Model...', or 'Add Code Generation
    // Item...'.
    

    Order.cs

    //------------------------------------------------------------------------------
    // <auto-generated>
    //     This code was generated from a template.
    //
    //     Manual changes to this file may cause unexpected behavior in your application.
    //     Manual changes to this file will be overwritten if the code is regenerated.
    // </auto-generated>
    //------------------------------------------------------------------------------
    
    namespace EntityFrameworkReports
    {
        using System;
        using System.Collections.Generic;
    
        public partial class Order
        {
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
            public Order()
            {
                this.Order_Details = new HashSet<Order_Detail>();
            }
    
            public int OrderID { get; set; }
            public string CustomerID { get; set; }
            public Nullable<int> EmployeeID { get; set; }
            public Nullable<System.DateTime> OrderDate { get; set; }
            public Nullable<System.DateTime> RequiredDate { get; set; }
            public Nullable<System.DateTime> ShippedDate { get; set; }
            public Nullable<int> ShipVia { get; set; }
            public Nullable<decimal> Freight { get; set; }
            public string ShipName { get; set; }
            public string ShipAddress { get; set; }
            public string ShipCity { get; set; }
            public string ShipRegion { get; set; }
            public string ShipPostalCode { get; set; }
            public string ShipCountry { get; set; }
    
            public virtual Customer Customer { get; set; }
            public virtual Employee Employee { get; set; }
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
            public virtual ICollection<Order_Detail> Order_Details { get; set; }
            public virtual Shipper Shipper { get; set; }
        }
    }
    

    Order_Detail.cs

    //------------------------------------------------------------------------------
    // <auto-generated>
    //     This code was generated from a template.
    //
    //     Manual changes to this file may cause unexpected behavior in your application.
    //     Manual changes to this file will be overwritten if the code is regenerated.
    // </auto-generated>
    //------------------------------------------------------------------------------
    
    namespace EntityFrameworkReports
    {
        using System;
        using System.Collections.Generic;
    
        public partial class Order_Detail
        {
            public int OrderID { get; set; }
            public int ProductID { get; set; }
            public decimal UnitPrice { get; set; }
            public short Quantity { get; set; }
            public float Discount { get; set; }
    
            public virtual Order Order { get; set; }
            public virtual Product Product { get; set; }
        }
    }
    

    Product.cs

    //------------------------------------------------------------------------------
    // <auto-generated>
    //     This code was generated from a template.
    //
    //     Manual changes to this file may cause unexpected behavior in your application.
    //     Manual changes to this file will be overwritten if the code is regenerated.
    // </auto-generated>
    //------------------------------------------------------------------------------
    
    namespace EntityFrameworkReports
    {
        using System;
        using System.Collections.Generic;
    
        public partial class Product
        {
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
            public Product()
            {
                this.Order_Details = new HashSet<Order_Detail>();
            }
    
            public int ProductID { get; set; }
            public string ProductName { get; set; }
            public Nullable<int> SupplierID { get; set; }
            public Nullable<int> CategoryID { get; set; }
            public string QuantityPerUnit { get; set; }
            public Nullable<decimal> UnitPrice { get; set; }
            public Nullable<short> UnitsInStock { get; set; }
            public Nullable<short> UnitsOnOrder { get; set; }
            public Nullable<short> ReorderLevel { get; set; }
            public bool Discontinued { get; set; }
    
            public virtual Category Category { get; set; }
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
            public virtual ICollection<Order_Detail> Order_Details { get; set; }
            public virtual Supplier Supplier { get; set; }
        }
    }
    

    Program.cs

    using System;
    using System.Windows.Forms;
    
    namespace EntityFrameworkReports
    {
        static class Program
        {
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main()
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new mainForm());
            }
        }
    }
    

    Region.cs

    //------------------------------------------------------------------------------
    // <auto-generated>
    //     This code was generated from a template.
    //
    //     Manual changes to this file may cause unexpected behavior in your application.
    //     Manual changes to this file will be overwritten if the code is regenerated.
    // </auto-generated>
    //------------------------------------------------------------------------------
    
    namespace EntityFrameworkReports
    {
        using System;
        using System.Collections.Generic;
    
        public partial class Region
        {
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
            public Region()
            {
                this.Territories = new HashSet<Territory>();
            }
    
            public int RegionID { get; set; }
            public string RegionDescription { get; set; }
        
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
            public virtual ICollection<Territory> Territories { get; set; }
        }
    }
    

    Shipper.cs

    //------------------------------------------------------------------------------
    // <auto-generated>
    //     This code was generated from a template.
    //
    //     Manual changes to this file may cause unexpected behavior in your application.
    //     Manual changes to this file will be overwritten if the code is regenerated.
    // </auto-generated>
    //------------------------------------------------------------------------------
    
    namespace EntityFrameworkReports
    {
        using System;
        using System.Collections.Generic;
    
        public partial class Shipper
        {
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
            public Shipper()
            {
                this.Orders = new HashSet<Order>();
            }
    
            public int ShipperID { get; set; }
            public string CompanyName { get; set; }
            public string Phone { get; set; }
        
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
            public virtual ICollection<Order> Orders { get; set; }
        }
    }
    

    Supplier.cs

    //------------------------------------------------------------------------------
    // <auto-generated>
    //     This code was generated from a template.
    //
    //     Manual changes to this file may cause unexpected behavior in your application.
    //     Manual changes to this file will be overwritten if the code is regenerated.
    // </auto-generated>
    //------------------------------------------------------------------------------
    
    namespace EntityFrameworkReports
    {
        using System;
        using System.Collections.Generic;
    
        public partial class Supplier
        {
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
            public Supplier()
            {
                this.Products = new HashSet<Product>();
            }
    
            public int SupplierID { get; set; }
            public string CompanyName { get; set; }
            public string ContactName { get; set; }
            public string ContactTitle { get; set; }
            public string Address { get; set; }
            public string City { get; set; }
            public string Region { get; set; }
            public string PostalCode { get; set; }
            public string Country { get; set; }
            public string Phone { get; set; }
            public string Fax { get; set; }
            public string HomePage { get; set; }
        
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
            public virtual ICollection<Product> Products { get; set; }
        }
    }
    

    Territory.cs

    //------------------------------------------------------------------------------
    // <auto-generated>
    //     This code was generated from a template.
    //
    //     Manual changes to this file may cause unexpected behavior in your application.
    //     Manual changes to this file will be overwritten if the code is regenerated.
    // </auto-generated>
    //------------------------------------------------------------------------------
    
    namespace EntityFrameworkReports
    {
        using System;
        using System.Collections.Generic;
    
        public partial class Territory
        {
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
            public Territory()
            {
                this.Employees = new HashSet<Employee>();
            }
    
            public string TerritoryID { get; set; }
            public string TerritoryDescription { get; set; }
            public int RegionID { get; set; }
    
            public virtual Region Region { get; set; }
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
            public virtual ICollection<Employee> Employees { get; set; }
        }
    }
    
    In This Article
    Back to top FlexCel Studio for the .NET Framework v7.24.0.0
    © 2002 - 2025 tmssoftware.com