使用实体模型和 LINQ 的 C# WPF SQL 多表 CRUD

Posted

技术标签:

【中文标题】使用实体模型和 LINQ 的 C# WPF SQL 多表 CRUD【英文标题】:C# WPF SQL multi-table CRUD using Entity Model and LINQ 【发布时间】:2020-04-15 19:55:07 【问题描述】:

我正在尝试使用实体模型将多个 SQL 表显示到数据网格以及更新、创建和删除行。在我加入实体模型对象后,我在从表中获取实体模型对象时遇到问题,因为现在实体的数据字段比它来自的原始模型对象多。我希望解决方案存在于某种 ViewModel 中,但是我无法弄清楚如何将对象从 ViewModel 中分离出来。几天来我一直在尝试解决这个问题,此时我希望我必须对我的代码进行一些认真的重组。任何提示将不胜感激。

这是负载实体模型(负载与货物负载有关,这与装载任何东西没有关系)

public partial class Load

    public int bol_num  get; set; 
    public string pro_num  get; set; 
    public string quote_num  get; set; 
    public string ref_num  get; set; 
    public Nullable<double> weight  get; set; 
    public Nullable<int> pieces  get; set; 
    public string commodity  get; set; 
    public Nullable<double> mileage  get; set; 
    public Nullable<decimal> carrier_rate  get; set; 
    public Nullable<decimal> customer_rate  get; set; 
    public Nullable<int> driver_id  get; set; 
    public Nullable<int> dispatch_id  get; set; 
    public Nullable<int> customer_id  get; set; 
    public Nullable<int> broker_id  get; set; 
    public Nullable<System.DateTime> pick_date  get; set; 
    public Nullable<System.TimeSpan> pick_time  get; set; 
    public Nullable<System.DateTime> drop_date  get; set; 
    public Nullable<System.TimeSpan> drop_time  get; set; 
    public Nullable<System.DateTime> last_updated_time  get; set; 
    public string load_status  get; set; 
    public Nullable<int> account_id  get; set; 

    public virtual Account Account  get; set; 
    //Constructors
    public Load(
        int bolInt, 
        string proString, 
        string quoteString, 
        string refString, 
        double weightDouble, 
        int piecesInt, 
        string commodityString, 
        double mileageDouble, 
        decimal carrier_rateDecimal, 
        decimal customer_rateDecimal,
        int driver_idInt,
        int dispatch_idInt,
        int customer_idInt,
        int broker_idInt,
        DateTime pick_dateDateTime,
        TimeSpan pick_timeTimeSpan,
        DateTime drop_dateDateTime,
        TimeSpan drop_timeTimeSpan,
        DateTime last_updated_timeDateTime,
        string load_statusString,
        int account_idInt
        )
    
        bol_num = bolInt;
        pro_num = proString;
        quote_num = quoteString;
        ref_num = refString;
        weight = weightDouble;
        pieces = piecesInt;
        commodity = commodityString;
        mileage = mileageDouble;
        carrier_rate = carrier_rateDecimal;
        customer_rate = customer_rateDecimal;
        driver_id = driver_idInt;
        dispatch_id = dispatch_idInt;
        customer_id = customer_idInt;
        broker_id = broker_idInt;
        pick_date = pick_dateDateTime;
        pick_time = pick_timeTimeSpan;
        drop_date = drop_dateDateTime;
        drop_time = drop_timeTimeSpan;
        last_updated_time = last_updated_timeDateTime;
        load_status = load_statusString;
        account_id = account_idInt;
    
    //Default
    public Load()
    

    

这是联系人对象的实体模型

public partial class Contact

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Contact()
    
        this.Accounts = new HashSet<Account>();
        this.Users = new HashSet<User>();
    

    public int id  get; set; 
    public string contact_name  get; set; 
    public string contact_phone  get; set; 
    public string contact_email  get; set; 

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<Account> Accounts  get; set; 
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<User> Users  get; set; 

这是处理添加新行和更新现有行的函数

//Update or Create Button
    private void update_btn_Click(object sender, RoutedEventArgs e)
    
        //Value Setting process
        try
        
            //Load model
            Load loadModel = new Load();
            //Get the load data from input fields
            loadModel.bol_num = Convert.ToInt32(bol_txt.Text.Trim());
            loadModel.load_status = loadStatus_cmbo.Text;
            loadModel.pro_num = pro_txt.Text.Trim();
            loadModel.quote_num = quote_txt.Text.Trim();
            loadModel.ref_num = ref_txt.Text.Trim();
            try
            
                loadModel.weight = Convert.ToDouble(weight_txt.Text.Trim());
            
            catch (System.FormatException ex) MessageBox.Show(ex.Message, "Invalid Pieces Entry", MessageBoxButton.OK, MessageBoxImage.Error);
            try
             
                loadModel.pieces = Convert.ToInt32(pieces_txt.Text.Trim()); 
            
            catch(System.FormatException ex)MessageBox.Show(ex.Message, "Invalid Pieces Entry", MessageBoxButton.OK, MessageBoxImage.Error);

            loadModel.commodity = commodity_txt.Text.Trim();
            loadModel.mileage = Convert.ToDouble(mileage_txt.Text.Trim());
            loadModel.carrier_rate = Convert.ToDecimal(carrierRate_txt.Text.Trim());
            loadModel.customer_rate = Convert.ToDecimal(customerRate_txt.Text.Trim());

            //Pick Date & Time setter
            loadModel.pick_date = pickDate_picker.SelectedDate.Value;
            loadModel.pick_time = TimeSpanBuilder(pickAptTime_txt.Text);

            //Drop Date & Time setter
            loadModel.drop_date = dropDate_picker.SelectedDate.Value;
            loadModel.drop_time = TimeSpanBuilder(dropAptTime_txt.Text);

            loadModel.driver_id = Convert.ToInt32(driver_txt.Text.Trim());
            loadModel.dispatch_id = Convert.ToInt32(dispatch_txt.Text.Trim());
            loadModel.customer_id = Convert.ToInt32(customer_txt.Text.Trim());
            loadModel.broker_id = Convert.ToInt32(broker_txt.Text.Trim());

            //Last updated
            loadModel.last_updated_time = DateTime.Now;

            //Save the load to the database
            using(HOTLOADDBEntities HOTLOADEntity = new HOTLOADDBEntities())
            
                if(loadModel.bol_num == 0)//Insert
                
                    HOTLOADEntity.Loads.Add(loadModel);
                    Clear();
                    MessageBox.Show("Saved Succesfully");
                
                else//Update
                
                    HOTLOADEntity.Entry(loadModel).State = EntityState.Modified;
                    Clear();
                
                //Save the changes
                HOTLOADEntity.SaveChanges();
                Search();
            

        
        //Entity Model Exception handler
        catch (DbEntityValidationException dbEx)
        
            foreach (var validationErrors in dbEx.EntityValidationErrors)
            
                foreach (var validationError in validationErrors.ValidationErrors)
                
                    Trace.TraceInformation(
                          "Class: 0, Property: 1, Error: 2",
                          validationErrors.Entry.Entity.GetType().FullName,
                          validationError.PropertyName,
                          validationError.ErrorMessage);
                
            
        
    

这是从 DataGrid 中选择对象的函数,由于我在我的搜索函数中添加了连接功能,该函数现在无法使用。

private void LoadBoard_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
    
        if (LoadBoard.SelectedIndex != -1)
        
            //Load model
            Load loadModel = (Load)LoadBoard.SelectedItem;
            using (HOTLOADDBEntities HOTLOADEntity = new HOTLOADDBEntities())
            
                loadModel = HOTLOADEntity.Loads.Where(x => x.bol_num == loadModel.bol_num).FirstOrDefault();
                bol_txt.Text = loadModel.bol_num.ToString();
                loadStatus_cmbo.SelectedIndex = ParseStatus(loadModel.load_status);
                pro_txt.Text = loadModel.pro_num.ToString();
                quote_txt.Text = loadModel.quote_num.ToString();
                ref_txt.Text = loadModel.ref_num.ToString();
                weight_txt.Text = loadModel.weight.ToString();
                pieces_txt.Text = loadModel.pieces.ToString();
                commodity_txt.Text = loadModel.commodity.ToString();
                mileage_txt.Text = loadModel.mileage.ToString();
                carrierRate_txt.Text = loadModel.carrier_rate.ToString();
                customerRate_txt.Text = loadModel.customer_rate.ToString();

                //Dates & Times
                pickDate_picker.Text = loadModel.pick_date.ToString();
                pickAptTime_txt.Text = TimeStringBuilder(loadModel.pick_time.Value);

                dropDate_picker.Text = loadModel.drop_date.ToString();
                dropAptTime_txt.Text = TimeStringBuilder(loadModel.drop_time.Value);

                driver_txt.Text = loadModel.driver_id.ToString();
                dispatch_txt.Text = loadModel.dispatch_id.ToString();
                customer_txt.Text = loadModel.customer_id.ToString();
                broker_txt.Text = loadModel.broker_id.ToString();

                lastUpdated_lbl.Content = "Last Updated: " + loadModel.last_updated_time;
            
            //Change Update/New button text
            update_btn.Content = "Update Load";

            //Enable copy & delete buttons
            delete_btn.IsEnabled = true;
            copy_btn.IsEnabled = true;
        
    

这是处理数据库查询的函数

private void Search()
    
        HOTLOADEntity = new HOTLOADDBEntities();

        //Timespan handling
        TimeSpan pickTimeStart = TimeSpan.Zero;
        TimeSpan pickTimeEnd = TimeSpan.Zero;
        TimeSpan dropTimeStart = TimeSpan.Zero;
        TimeSpan dropTimeEnd = TimeSpan.Zero;
        try  pickTimeStart = TimeSpanBuilder(pickTimeStartSearch_txt.Text); catch (System.Exception)//Ignore
        
        try pickTimeEnd = TimeSpanBuilder(pickTimeEndSearch_txt.Text); catch (System.Exception)//Ignore
        
        try  dropTimeStart = TimeSpanBuilder(dropTimeStartSearch_txt.Text); catch (System.Exception)//Ignore
        
        try  dropTimeEnd = TimeSpanBuilder(dropTimeEndSearch_txt.Text); catch (System.Exception)//Ignore
        

        var matchedLoads = (
                        from loadsTable in HOTLOADEntity.Loads
                        join driversTable in HOTLOADEntity.Contacts on loadsTable.driver_id equals driversTable.id
                        /*
                        where 
                        loadsTable.bol_num.ToString().Contains(bolSearch_txt.Text) &&
                        loadsTable.pro_num.ToString().Contains(proSearch_txt.Text) &&
                        loadsTable.quote_num.ToString().Contains(quoteSearch_txt.Text) &&
                        loadsTable.ref_num.ToString().Contains(refSearch_txt.Text) &&

                        //Pick Date search terms
                        ((pickDateStart_dtpckr.SelectedDate == null || loadsTable.pick_date >= pickDateStart_dtpckr.SelectedDate) &&

                        (pickDateEnd_dtpckr.SelectedDate == null || loadsTable.pick_date <= pickDateEnd_dtpckr.SelectedDate)) &&

                        //Pick Time search terms
                        ((pickTimeStartSearch_txt.Text == null || pickTimeStart == TimeSpan.Zero || loadsTable.pick_time.Value >= pickTimeStart) &&
                        (pickTimeEndSearch_txt.Text == null || pickTimeEnd == TimeSpan.Zero || loadsTable.pick_time.Value <= pickTimeEnd)) &&

                        //Drop Date Search terms
                        ((dropDateStart_dtpckr.SelectedDate == null || loadsTable.drop_date >= dropDateStart_dtpckr.SelectedDate) &&

                        (dropDateEnd_dtpckr.SelectedDate == null || loadsTable.drop_date <= dropDateEnd_dtpckr.SelectedDate)) &&

                        //Drop Time search terms
                        ((dropTimeStartSearch_txt.Text == null || dropTimeStart == TimeSpan.Zero || loadsTable.drop_time.Value >= dropTimeStart) &&
                        (dropTimeEndSearch_txt.Text == null || dropTimeEnd == TimeSpan.Zero || loadsTable.drop_time.Value <= dropTimeEnd))
                        */
                        select new
                        
                            bol_num = loadsTable.bol_num,
                            load_status = loadsTable.load_status,
                            pro_num = loadsTable.pro_num,
                            quote_num = loadsTable.quote_num,
                            ref_num = loadsTable.ref_num,
                            weight = loadsTable.weight,
                            pieces = loadsTable.pieces,
                            commodity = loadsTable.commodity,
                            mileage = loadsTable.mileage,
                            carrier_rate = loadsTable.carrier_rate,
                            customer_rate = loadsTable.customer_rate,
                            pick_date = loadsTable.pick_date,
                            pick_time = loadsTable.pick_time,
                            drop_date = loadsTable.drop_date,
                            drop_time = loadsTable.drop_time,
                            last_updated_time = loadsTable.last_updated_time,
                            driver_id = loadsTable.driver_id,
                            driver_name = driversTable.contact_name,
                            driver_phone = driversTable.contact_phone,
                            driver_email = driversTable.contact_email,
                            dispatch_id = loadsTable.dispatch_id,
                            customer_id = loadsTable.customer_id,
                            broker_id = loadsTable.broker_id,
                            account_id = loadsTable.account_id
                        
                        ).ToList();

        LoadBoard.ItemsSource = matchedLoads;
    

不确定这是否相关,但这是 DataGrid 的关联 XAML

<DataGrid Name="LoadBoard" AutoGenerateColumns="False" AlternatingRowBackground="Cornsilk" Background="Ivory" IsReadOnly="True" MouseDoubleClick="LoadBoard_MouseDoubleClick">
                <!--Datagrid Columns-->
                <DataGrid.Columns>
                    <DataGridTextColumn x:Name="bolColumn" Header="BOL#" Binding="Binding bol_num"/>
                    <DataGridTextColumn x:Name="statusColumn" Header="Status" Binding="Binding load_status"/>
                    <DataGridTextColumn x:Name="proColumn" Header="Pro#" Binding="Binding pro_num"/>
                    <DataGridTextColumn x:Name="quoteColumn" Header="Quote#" Binding="Binding quote_num"/>
                    <DataGridTextColumn x:Name="refColumn" Header="Ref" Binding="Binding ref_num"/>
                    <DataGridTextColumn x:Name="weightColumn" Header="Weight" Binding="Binding weight"/>
                    <DataGridTextColumn x:Name="piecesColumn" Header="Pieces" Binding="Binding pieces"/>
                    <DataGridTextColumn x:Name="commodityColumn" Header="Commodity" Binding="Binding commodity"/>
                    <DataGridTextColumn x:Name="mileageColumn" Header="Mileage" Binding="Binding mileage"/>
                    <DataGridTextColumn x:Name="carrierColumn" Header="Carrier Rate" Binding="Binding carrier_rate"/>
                    <DataGridTextColumn x:Name="customerRateColumn" Header="Customer Rate" Binding="Binding customer_rate"/>
                    <DataGridTextColumn x:Name="pickDateColumn" Header="Pick Date" Binding="Binding pick_date, StringFormat= \0:MM/dd/yyyy\" />
                    <DataGridTextColumn x:Name="pickTimeColumn" Header="Pick Time" Binding="Binding pick_time, StringFormat=hh\\:mm" />
                    <DataGridTextColumn x:Name="dropDateColumn" Header="Drop Date" Binding="Binding drop_date, StringFormat= \0:MM/dd/yyyy\" />
                    <DataGridTextColumn x:Name="dropTimeColumn" Header="Drop Time" Binding="Binding drop_time, StringFormat=hh\\:mm" />
                    <DataGridTextColumn x:Name="lastUpdatedColumn" Header="Last Updated" Binding="Binding last_updated_time" />
                    <DataGridTextColumn x:Name="driverNameColumn" Header="Driver Name" Binding="Binding driver_name"/>
                    <DataGridTextColumn x:Name="driverPhoneColumn" Header="Driver Phone" Binding="Binding driver_phone"/>
                    <DataGridTextColumn x:Name="driverEmailColumn" Header="Driver Email" Binding="Binding driver_email"/>
                    <DataGridTextColumn x:Name="DispatchColumn" Header="Dispatch" Binding="Binding dispatch_id"/>
                    <DataGridTextColumn x:Name="CustomerColumn" Header="Customer" Binding="Binding customer_id"/>
                    <DataGridTextColumn x:Name="BrokerColumn" Header="Broker" Binding="Binding broker_id"/>
                </DataGrid.Columns>
            </DataGrid>

【问题讨论】:

常见的解决方案是为存储和表示级别设置单独的类,并在需要时在它们之间进行映射 我该怎么做?我尝试使用视图模型,但无法使用 CRUD 操作。 【参考方案1】:

所以我最终重新尝试了 View Model 解决方案并最终让它工作。这是我以前这样做的代码。

查看模型类

class ViewModel

    //Load Fields
    public int bol_num  get; set; 
    public string pro_num  get; set; 
    public string quote_num  get; set; 
    public string ref_num  get; set; 
    public Nullable<double> weight  get; set; 
    public Nullable<int> pieces  get; set; 
    public string commodity  get; set; 
    public Nullable<double> mileage  get; set; 
    public Nullable<decimal> carrier_rate  get; set; 
    public Nullable<decimal> customer_rate  get; set; 
    public Nullable<int> driver_id  get; set; 
    public Nullable<int> dispatch_id  get; set; 
    public Nullable<int> customer_id  get; set; 
    public Nullable<int> broker_id  get; set; 
    public Nullable<System.DateTime> pick_date  get; set; 
    public Nullable<System.TimeSpan> pick_time  get; set; 
    public Nullable<System.DateTime> drop_date  get; set; 
    public Nullable<System.TimeSpan> drop_time  get; set; 
    public Nullable<System.DateTime> last_updated_time  get; set; 
    public string load_status  get; set; 
    public Nullable<int> account_id  get; set; 

    //Driver Fields
    public string driverContact_name  get; set; 
    public string driverContact_phone  get; set; 
    public string driverContact_email  get; set; 

修改后的搜索功能

private void Search()
    
        HOTLOADEntity = new HOTLOADDBEntities();

        //Timespan handling
        TimeSpan pickTimeStart = TimeSpan.Zero;
        TimeSpan pickTimeEnd = TimeSpan.Zero;
        TimeSpan dropTimeStart = TimeSpan.Zero;
        TimeSpan dropTimeEnd = TimeSpan.Zero;
        try  pickTimeStart = TimeSpanBuilder(pickTimeStartSearch_txt.Text); catch (System.Exception)//Ignore
        
        try pickTimeEnd = TimeSpanBuilder(pickTimeEndSearch_txt.Text); catch (System.Exception)//Ignore
        
        try  dropTimeStart = TimeSpanBuilder(dropTimeStartSearch_txt.Text); catch (System.Exception)//Ignore
        
        try  dropTimeEnd = TimeSpanBuilder(dropTimeEndSearch_txt.Text); catch (System.Exception)//Ignore
        

        var matchedLoads = (
                        from loads in HOTLOADEntity.Loads
                        join drivers in HOTLOADEntity.Contacts
                        on loads.driver_id equals drivers.id

                        where 
                        loads.bol_num.ToString().Contains(bolSearch_txt.Text) &&
                        loads.pro_num.ToString().Contains(proSearch_txt.Text) &&
                        loads.quote_num.ToString().Contains(quoteSearch_txt.Text) &&
                        loads.ref_num.ToString().Contains(refSearch_txt.Text) &&

                        //Pick Date search terms
                        ((pickDateStart_dtpckr.SelectedDate == null || loads.pick_date >= pickDateStart_dtpckr.SelectedDate) &&

                        (pickDateEnd_dtpckr.SelectedDate == null || loads.pick_date <= pickDateEnd_dtpckr.SelectedDate)) &&

                        //Pick Time search terms
                        ((pickTimeStartSearch_txt.Text == null || pickTimeStart == TimeSpan.Zero || loads.pick_time.Value >= pickTimeStart) &&
                        (pickTimeEndSearch_txt.Text == null || pickTimeEnd == TimeSpan.Zero || loads.pick_time.Value <= pickTimeEnd)) &&

                        //Drop Date Search terms
                        ((dropDateStart_dtpckr.SelectedDate == null || loads.drop_date >= dropDateStart_dtpckr.SelectedDate) &&

                        (dropDateEnd_dtpckr.SelectedDate == null || loads.drop_date <= dropDateEnd_dtpckr.SelectedDate)) &&

                        //Drop Time search terms
                        ((dropTimeStartSearch_txt.Text == null || dropTimeStart == TimeSpan.Zero || loads.drop_time.Value >= dropTimeStart) &&
                        (dropTimeEndSearch_txt.Text == null || dropTimeEnd == TimeSpan.Zero || loads.drop_time.Value <= dropTimeEnd))

                        select new ViewModel
                        
                            //Load properties
                            bol_num = loads.bol_num,
                            load_status = loads.load_status,
                            pro_num = loads.pro_num,
                            quote_num = loads.quote_num,
                            ref_num = loads.ref_num,
                            weight = loads.weight,
                            pieces = loads.pieces,
                            commodity = loads.commodity,
                            mileage = loads.mileage,
                            carrier_rate = loads.carrier_rate,
                            customer_rate = loads.customer_rate,
                            pick_date = loads.pick_date,
                            pick_time = loads.pick_time,
                            drop_date = loads.drop_date,
                            drop_time = loads.drop_time,
                            last_updated_time = loads.last_updated_time,
                            driver_id = loads.driver_id,
                            dispatch_id = loads.dispatch_id,
                            customer_id = loads.customer_id,
                            broker_id = loads.broker_id,
                            account_id = loads.account_id,

                            //Driver properties
                            driverContact_name = drivers.contact_name,
                            driverContact_phone = drivers.contact_phone,
                            driverContact_email = drivers.contact_email,
                        );

        LoadBoard.ItemsSource = matchedLoads.ToList();
    

修改了数据网格双击按钮上的选择

private void LoadBoard_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
    
        if (LoadBoard.SelectedIndex != -1)
        
            //Load model
            ViewModel SelectedItem = (ViewModel)LoadBoard.SelectedItem;
            Load loadModel = HOTLOADEntity.Loads.Find(SelectedItem.bol_num);
            using (HOTLOADDBEntities HOTLOADEntity = new HOTLOADDBEntities())
            
                loadModel = HOTLOADEntity.Loads.Where(x => x.bol_num == loadModel.bol_num).FirstOrDefault();
                bol_txt.Text = loadModel.bol_num.ToString();
                loadStatus_cmbo.SelectedIndex = ParseStatus(loadModel.load_status);
                pro_txt.Text = loadModel.pro_num.ToString();
                quote_txt.Text = loadModel.quote_num.ToString();
                ref_txt.Text = loadModel.ref_num.ToString();
                weight_txt.Text = loadModel.weight.ToString();
                pieces_txt.Text = loadModel.pieces.ToString();
                commodity_txt.Text = loadModel.commodity.ToString();
                mileage_txt.Text = loadModel.mileage.ToString();
                carrierRate_txt.Text = loadModel.carrier_rate.ToString();
                customerRate_txt.Text = loadModel.customer_rate.ToString();

                //Dates & Times
                pickDate_picker.Text = loadModel.pick_date.ToString();
                pickAptTime_txt.Text = TimeStringBuilder(loadModel.pick_time.Value);

                dropDate_picker.Text = loadModel.drop_date.ToString();
                dropAptTime_txt.Text = TimeStringBuilder(loadModel.drop_time.Value);

                driver_txt.Text = loadModel.driver_id.ToString();
                dispatch_txt.Text = loadModel.dispatch_id.ToString();
                customer_txt.Text = loadModel.customer_id.ToString();
                broker_txt.Text = loadModel.broker_id.ToString();

                lastUpdated_lbl.Content = "Last Updated: " + loadModel.last_updated_time;
            
            //Change Update/New button text
            update_btn.Content = "Update Load";

            //Enable copy & delete buttons
            delete_btn.IsEnabled = true;
            copy_btn.IsEnabled = true;
        
    

【讨论】:

以上是关于使用实体模型和 LINQ 的 C# WPF SQL 多表 CRUD的主要内容,如果未能解决你的问题,请参考以下文章

具有 LINQ 关联的 C# 和 ADO .NET 实体数据模型以及同一表的实体

带有 LinqToSql System.Data.Linq.DuplicateKeyException 的 C# 和 SQL Server 数据库出错:无法使用已在使用的键添加实体。

实体框架/Linq to sql 模型到业务模型

在 BLL 或 UI 中使用 Linq-to-SQL 实体?

3-实体数据模型与LINQ-排序

通过 LINQ-to-SQl 加载数据集